Counting Divisors HDU

Counting Divisors

 HDU - 6069 

题意:给定区间[a,b]和k,求xk有多少因子(x属于[a,b]),求和。

a、b最大可达到1e12,但是b-a<1e6。

一开始愚蠢的一个一个分解然后去求有多少因子然后求和,范围那么大裸裸的超时啊!

可以枚举素数,对每一个素数,把区间内所有可以分解的进行分解。

最后再求和。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn=1e6+10;
 5 const int mod=998244353;
 6 int vis[maxn];
 7 int pri[maxn];
 8 ll ans[maxn],num[maxn];
 9 int cnt=0;
10 void init(){
11     cnt=0;
12     memset(vis,0,sizeof(vis));
13     for(ll i=2;i<maxn;i++){
14         if(!vis[i]){
15             pri[cnt++]=i;
16             for(ll j=i*i;j<maxn;j+=i)
17                 vis[j]=1;
18         }
19     }
20 }
21 
22 int main(){
23     init();
24     int t;
25     scanf("%d",&t);
26     while(t--){
27         ll a,b,k;
28         scanf("%lld%lld%lld",&a,&b,&k);
29         int r=b-a+1;
30         for(int i=0;i<r;i++){
31             num[i]=i+a;
32             ans[i]=1;
33         }
34         for(int i=0;i<cnt;i++){
35             int x=pri[i];
36             ll s=(x-a%x)%x;  //!!
37             for(;s<r;s+=x){
38                 int temp=0;
39                 while(num[s]%x==0){
40                     temp++;
41                     num[s]/=x;
42                 }
43                 ans[s]*=(k*temp+1);
44                 if(ans[s]>=mod) ans[s]%=mod;
45             }
46         }
47         ll res=0;
48         for(int i=0;i<r;i++){
49             if(num[i]>1) ans[i]=ans[i]*(k+1)%mod;
50             res+=ans[i];
51             if(res>=mod) res-=mod;
52         }
53 
54         printf("%d
",res);
55     }
56 }
View Code