HDU 6069 Counting Divisors 【2017多校联赛4】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Jane_JXR/article/details/76653742

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6069

题意:求[l,r]范围内i^k的因子个数和。

分析:先根据唯一分解定理把当前数分解成素数乘积的形式
素因子分解:n = p1 ^ e1 * p2 ^ e2 *..........*pn ^ en
则n的因子个数为(e1+1)*(e2+1)*.........*(en+1)
n^k的因子的个数为:(e1*k+1)*(e2*k+1)*.........*(en*k+1)
所以我们可以筛出[l,r]范围内[1,1e6]素因子的个数,然后判断是否为1再做相应处理。如果不为1,则必有大于1e6的素数。突破口是区间的限制。

反思:做比赛时想到筛素数去处理,中间的关系也找到了,但不知道怎么去处理大于1e6的素数,也没想过去存中间的结果,还是思考的不够,思维方式的问题。。。

CODE:

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<math.h>
#define INF 0x3f3f3f3f
#define lson l,m,root<<1
#define rson m+1,r,root<<1|1
typedef long long LL;
using namespace std;
const int maxn=1000005;
const int mod=998244353;
LL l,r,k;
LL prime[maxn];
void getprime()
{
    memset(prime,0,sizeof(prime));
    for(int i=2; i<=maxn; i++)
    {
        if(!prime[i])
            prime[++prime[0]]=i;
        for(int j=1; j<=prime[0]&&prime[j]<maxn/i; j++)
        {
            prime[prime[j]*i]=1;
            if(i%prime[j]==0)
                break;
        }
    }
}
LL cnt[maxn],q[maxn];
int main()
{
    int t;
    scanf("%d",&t);
    getprime();
    while(t--)
    {
        scanf("%lld%lld%lld",&l,&r,&k);
        LL sum=0;
        for(int i=0; i<=r-l; i++)
            cnt[i]=1,q[i]=l+i;//把[l,r]的数存在[0,r-l]内
        for(int i=1; i<=prime[0]&&prime[i]<=r; i++)
        {
            LL j=l/prime[i]+(l%prime[i]!=0);//注意
            for(j=j*prime[i]; j<=r; j+=prime[i])
            {
                LL count=0;
                while(q[j-l]%prime[i]==0)
                    q[j-l]/=prime[i],count++;
                cnt[j-l]*=(count*k+1)%mod;
                cnt[j-l]%=mod;
            }
        }
        for(int i=0; i<=r-l; i++)
        {
            if(q[i]!=1)
                sum+=((k+1)*cnt[i])%mod;//[l,r]范围内有大于1e6的素数
            else
                sum+=cnt[i];
            sum%=mod;
            // cout<<cnt[i]<<" ";
        }
        printf("%lld\n",sum);
    }
    return 0;
}

Counting Divisors

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1319    Accepted Submission(s): 469


Problem Description
In mathematics, the function  d(n) denotes the number of divisors of positive integer  n.

For example,  d(12)=6 because  1,2,3,4,6,12 are all  12's divisors.

In this problem, given  l,r and  k, your task is to calculate the following thing :

(i=lrd(ik))mod998244353

 

Input
The first line of the input contains an integer  T(1T15), denoting the number of test cases.

In each test case, there are  3 integers  l,r,k(1lr1012,rl106,1k107).
 

Output
For each test case, print a single line containing an integer, denoting the answer.
 

Sample Input
 
  
3 1 5 1 1 10 2 1 100 3
 

Sample Output
 
  
10 48 2302
 

Source
 

猜你喜欢

转载自blog.csdn.net/Jane_JXR/article/details/76653742