hdu 6069 Counting Divisors (素数)

来源:互联网 发布:spss统计分析数据论文 编辑:程序博客网 时间:2024/05/18 00:50

根据约数个数定理:n=p1^a1×p2^a2×p3^a3*…*pk^ak,n的约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1).

若i=p1^a1×p2^a2×p3^a3*…*pk^ak,则i^K=p1^(a1*K)×p2^(a2*K)×p3^(a3*K)*…*pk^(ak*K),i^K的约数的个数就是(a1*K+1)(a2*K+1)(a3*K+1)…(ak*K+1)

首先同上,n可以分解质因数:n=p1^a1×p2^a2×p3^a3*…*pk^ak,
由约数定义可知p1^a1的约数有:p1^0, p1^1, p1^2......p1^a1 ,共(a1+1)个;同理p2^a2的约数有(a2+1)个......pk^ak的约数有(ak+1)个。
故根据乘法原理:n的约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1)。
有了这个原理就来到了最难想的地方怎么在时间复杂度的允许下完成这个题。l-r有1e6个,15组测试数据,时间就差不多了,遍历l-r,根据l-r算是不科学的。不可能完成的任务。

所以只能遍历素数的个数,素数大概有7万多接近1e5,还有发挥的空间,每个从prime【0】到prime【n】算出在l-r中每个能整除prime【i】的数,算出他能整除t次prime【i】。cnt【i】就乘以(t*k+1)因为求的是i^k有所以能整除prime【i】(t+k)次

时间复杂度大概是m*logm

#include "cstdio"#include "iostream"#include "cstring"#include <algorithm>using namespace std;const int maxn= 1e6+10;long long mod=998244353;bool visit[maxn]= {0};long long prime[maxn];//cnt[i]代表i+l的因子数,former[i]代表i+l这个数long long cnt[maxn],former[maxn];int N=0;void init(){    for(long long i=2; i<maxn; i++)    {        if(!visit[i])            prime[N++]=i;        for(long long j=0; j<N; j++)        {            long long k=i*prime[j];            if(k>maxn)break;            visit[k]=1;        }    }}int main(){    int t;    init();    scanf("%d",&t);    while(t--)    {        long long l,r,k;        scanf("%lld%lld%lld",&l,&r,&k);        //初始化cnt,former        long long ans=0;        if(l==1)ans++,l++;        for(long long i=0; i<=r-l; i++)cnt[i]=1,former[i]=i+l;        for(long long i=0; prime[i]*prime[i]<=r; i++)        {            long long p=l/prime[i]+(l%prime[i]!=0);            for(long long j=p*prime[i]; j<=r; j+=prime[i])            {                long long tmp=0;                while((former[j-l]%prime[i])==0)                {                    former[j-l]/=prime[i];                    tmp++;                }                cnt[j-l]*=(tmp*k+1)%mod;                cnt[j-l]%=mod;            }        }        for(long long i=0; i<=r-l; i++)        {            if(former[i]!=1)                ans=ans+(cnt[i]*(k+1))%mod;            else ans=ans+cnt[i];            ans%=mod;        }        printf("%lld\n",ans);    }    return 0;}