【数论】hdu 6069 Counting Divisors

来源:互联网 发布:01年nba总决赛数据 编辑:程序博客网 时间:2024/05/21 21:36

Counting Divisors
Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 2815    Accepted Submission(s): 1040
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 :

Input
The first line of the input contains an integer T(1≤T≤15), denoting the number of test cases.
In each test case, there are 3 integers l,r,k(1≤l≤r≤1012,r−l≤106,1≤k≤107).
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

题意:d(i):i 的因子个数,给定范围内任意l,r,k 计算如上公式值;
思路:d(i),把 i 分解为质因子的形式,然后各个质因子的幂+1,然后相乘,就是 i 的因子个数;
开一个数组来保存1~1e6的质数,1e6范围内的质数就够用了;
之前的代码是把 l , r 的循环放在外部,质数的循环放在内部,用来求每一个数的不同质因子的个数,这样的复杂度是n*tot(质数的个数)
把质数的循环放在外部的话,可以优化:
代码:
#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;#define ll long long#define mod 998244353const int N=1000006;int is_prime[N+10],prime[N+10];int tot=0;ll ans;ll l,r,k;void get_prime(){    int i,j;    tot=0;    memset(is_prime,false,sizeof(is_prime));    for(i=2; i<N; i++)    {        if(!is_prime[i])            prime[tot++]=i;        for(j=0; (j<tot)&&(i*prime[j]<N); j++)        {            is_prime[i*prime[j]]=true;            if(i%prime[j]==0)                break;        }    }}ll f[N],g[N];void work(){    for(ll i=l; i<=r; i++)        f[i-l]=i,g[i-l]=1;    for(int i=0; i<tot; i++)    {        if(prime[i]*prime[i]>r) // 优化 ,如果这个素数的平方都大于r,那么l~r没有能够整除这个素数和这个素数之后的所有素数了;            break;        for(ll j=l/prime[i]*prime[i]; j<=r; j+=prime[i]) //优化 ,每一次都是j+=prime[i];        {            if(j>=l)            {                int cnt=0;                while(f[j-l]%prime[i]==0)                {                    cnt++;                    f[j-l]/=prime[i];                }                g[j-l]=g[j-l]*(cnt*k+1)%mod;            }        }    }    for(ll i=l; i<=r; i++)    {        if(f[i-l]>1)            g[i-l]=g[i-l]*(k+1)%mod;        ans=ans+g[i-l];        if(ans>=mod)            ans%=mod;    }}int main(){    int T;    scanf("%d",&T);    get_prime();    while(T--)    {        ans=0;        scanf("%I64d%I64d%I64d",&l,&r,&k);        work();        printf("%I64d\n",ans%mod);    }    return 0;}

代码中有 l / prime[i] * prime[i] ,这个代码是找到离 l 最近的,小于等与 l 的,能够整除 prime[i] 的数;
参考队友的思路,代码,≧ ﹏ ≦
原创粉丝点击