hdu 6069 统计区间约数的个数 2017 Multi-University Training Contest

来源:互联网 发布:union all 不同数据库 编辑:程序博客网 时间:2024/06/14 06:48

Counting Divisors

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


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
31 5 11 10 21 100 3
 

Sample Output
10482302



首先我们要知道一个定理

一个数的约数的个数等于,唯一分解成质数的形式后,每一个指数加一后累乘的结果


本题就比较简单了,比赛的时候傻逼了

枚举10的六次方以内的质数,不超过八万好像,忘了,可以运行程序看看就知道了,反正不多

然后再区间内部,枚举质数的倍数,这样可以减少很多运算量,然后计算这个质数在这个倍数里面可以分解得到多少个,即上面说的指数


需要注意的是,分解后可能会有大于10的六次方的指数,最后把这些数另外处理一下即可



#include<math.h>#include<stdio.h>#include<algorithm>using namespace std;#define LL long long#define mod 998244353#define MAXN 1000006LL sum[MAXN],num[MAXN];LL primer[MAXN];LL flag[MAXN];int cnt=0;void get_primer(){    flag[0]=flag[1]=1;    LL sqrtmaxn=(LL)sqrt((double)MAXN);    for(int i=2;i<MAXN;i++){        if(primer[i]==0){            flag[i]=flag[i-1];            primer[cnt++]=i;            if(i<sqrtmaxn)                for(int j=i*i;j<MAXN;j+=i)                    primer[j]=1;        }        else            flag[i]=(flag[i-1]*i)%mod;    }}int main(){    int T;    get_primer();    LL a,b,c,ans;    //freopen("in.txt","r",stdin);    scanf("%d",&T);    while(T--)    {        scanf("%lld%lld%lld",&a,&b,&c);        for(int i=0;i<=b-a+1;i++)            sum[i]=1,num[i]=a+i;        LL pos,t,temp;        for(int i=0;i<cnt;i++){            if(primer[i]>(b/2+1))                break;            t=a/primer[i];            if(a%primer[i]) t++;            pos=t*primer[i];            for(LL j=pos;j<=b;j+=primer[i]){                t=0;                while(num[j-a]%primer[i]==0)                    num[j-a]/=primer[i],t++;                sum[j-a]=sum[j-a]*(c*t+1)%mod;            }        }        ans=0;        for(LL j=a;j<=b;j++){            if(num[j-a]>1)                sum[j-a]=sum[j-a]*(c+1)%mod;            ans=(ans+sum[j-a])%mod;        }        printf("%lld\n",ans);    }    return 0;}


阅读全文
0 0