2017 Multi-University Training Contest - Team 4 hdu6069 Counting Divisors
地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6069
题目:
Counting Divisors
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1235 Accepted Submission(s): 433
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 :
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(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).
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
Source
思路:
首先需要知道:一个数可以用唯一分解定理表示成:n=p1^a1*p2^2......*pn^an
质约数个数为(a1+1)*(a2+1)*....*(an+1)
那么n^k的质约数个数为(a1*k+1)*(a2*k+1)*.....*(an*k+1)
所以这题的关键是求l,r区间每个数的质约数有那些,且次数是多少。
考虑到:l,r最大为1e12,所以枚举1-1e6内的所有素数后即可知道l,r中每个数的质约数有哪些,同时可以知道次数是多少
但是直接在1-1e6的素数表内查找l,r中的某个数的素约数的时间复杂度是O(1e6),显然不可行。
所以可以通过线性筛的思想来求:对于1-1e6的素数,考虑他会在l,r内筛掉哪些数即可。
因为1e12每个数最多有20左右的质约数,所以时间复杂度是O((r-l)*20)+O(1e5)(质数表大小)
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define MP make_pair 6 #define PB push_back 7 typedef long long LL; 8 typedef pair<int,int> PII; 9 const double eps=1e-8; 10 const double pi=acos(-1.0); 11 const int K=1e6+7; 12 const int mod=998244353; 13 14 LL ql,qr,qk,cnt,ls[K],sum[K],pr[K]; 15 bool pa[K]; 16 void init(void) 17 { 18 for(int i=2;i<=1000000;i++) 19 if(!pa[i]) 20 { 21 pr[cnt++]=i; 22 for(int j=i*2;j<=1000000;j+=i) pa[j]=1; 23 } 24 } 25 LL sc(int t) 26 { 27 LL ans=0; 28 for(LL i=ql;i<=qr;i++) sum[i-ql]=1,ls[i-ql]=i; 29 for(int i=0;i<cnt;i++) 30 { 31 for(LL j=max(2LL,(ql+pr[i]-1)/pr[i])*pr[i];j<=qr;j+=pr[i]) 32 { 33 LL cnt=0; 34 while(ls[j-ql]%pr[i]==0) ls[j-ql]/=pr[i],cnt++; 35 sum[j-ql]=(sum[j-ql]*(qk*cnt+1))%mod; 36 } 37 } 38 for(LL i=ql;i<=qr;i++) 39 { 40 if(ls[i-ql]!=1) sum[i-ql]=(sum[i-ql]*(qk+1))%mod; 41 ans+=sum[i-ql]; 42 if(ans>=mod) ans-=mod; 43 } 44 return ans; 45 } 46 47 int main(void) 48 { 49 //freopen("in.acm","r",stdin); 50 int t;scanf("%d",&t); 51 init(); 52 while(t--) 53 { 54 scanf("%lld%lld%lld",&ql,&qr,&qk); 55 printf("%lld\n",sc(t)); 56 } 57 return 0; 58 }
作者:weeping
出处:www.cnblogs.com/weeping/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。