hdu 6069 Counting Divisors (素数)
2017-08-04 10:29
375 查看
根据约数个数定理: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
若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; }
相关文章推荐
- hdu 6069 素数
- hdu 6069 素数
- hdu 6069 素数
- HDU 6069 Counting Divisors(枚举区间)(素数筛模版)
- hdu 6069 素数
- hdu 6069 素数
- HDU 2017 多校联合训练赛4 4003 6069 Counting Divisors 素数筛和素因数分解
- HDU 6069 Counting Divisors (素数)
- hdu 6069 素数
- hdu 6069 素数
- [hdu 6069]素数筛+区间质因数分解
- 【HDU 6069 Counting Divisors】 + 素数筛 & 思维
- hdu 6069 素数
- HDU 6069 Counting Divisors【素数筛】【约数个数定理】
- hdu 6069 素数
- HDU 6069 Counting Divisors (素数+筛法)
- hdu 6069 素数
- HDU 6069 素数筛+分解质因子
- HDU 6069 数学题,区间素数筛
- HDU 6069 数论 区间素数筛(+赛后反思