HDOJ 6069 素数筛法(数学)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDOJ 6069 素数筛法(数学)相关的知识,希望对你有一定的参考价值。
Counting Divisors
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 3041 Accepted Submission(s): 1130
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
思路:先将1000005以内的素数打表(素数筛法O(n)). 然后将每个数拆成S=p1^a1*p2*^a2...*pn^an 的形式则 d(S)=(1+a1)*(1+a2)....*(1+an);
实现方法:1.用num[] 存下当前拆分后剩下的数字
2.用ans[i]存下第i个数字此时的已拆分的累乘结果
3.将素数从小到大扫一遍,对[l,r]每个数字进行拆分,逐一更新ans[i]的值
代码:
1 #include<bits/stdc++.h> 2 3 typedef long long ll; 4 using namespace std; 5 6 const int N=1e6+5; 7 const int inf=1e9; 8 const int mod=998244353; 9 10 ll l,r,k; 11 bool v[N]; 12 ll ans[N]; 13 ll num[N]; 14 int pri[N]; 15 int pcnt; 16 void init() 17 { 18 pcnt = 0;//素数筛 19 for(int i = 2; i <= N; i++) 20 { 21 if(!v[i]) 22 pri[pcnt++] = i; 23 for(int j = 0; j < pcnt && pri[j] <= N/i; j++) 24 { 25 v[i*pri[j]] = 1; 26 if(i % pri[j]==0) break; 27 } 28 } 29 } 30 void f() 31 { 32 for(ll i=l;i<=r;i++)//初始化记录数组 33 num[i-l]=i,ans[i-l]=1; 34 } 35 int main() 36 { 37 int t; 38 init(); 39 scanf("%d",&t); 40 while(t--) 41 { 42 scanf("%lld%lld%lld",&l,&r,&k); 43 f(); 44 for(int i=0;i<pcnt&&pri[i]<=1000000;i++){//限制质因子大小 45 ll p=pri[i]; 46 ll d=l/p+(l%p>0); 47 if(d==1) d=2;//l<=p 的情况在最后判断处理 48 for(ll j=d*p;j<=r;j+=p){ 49 ll cnt=0; 50 while(num[j-l]%p==0){ 51 num[j-l]/=p; 52 cnt++; 53 } 54 ans[j-l]=(ans[j-l]%mod)*((1+k*cnt)%mod)%mod; 55 } 56 } 57 ll sum=0; 58 for(ll i=l;i<=r;i++){ 59 if(num[i-l]>1)//还存在一个大于1000000的因子,再乘上k+1 60 sum=(sum+ans[i-l]*(k+1))%mod; 61 else 62 sum=(sum+ans[i-l])%mod; 63 } 64 printf("%lld\n",sum); 65 } 66 67 }
以上是关于HDOJ 6069 素数筛法(数学)的主要内容,如果未能解决你的问题,请参考以下文章