第四場 hdu 6069 Counting Divisors (逆向思惟)

http://acm.hdu.edu.cn/showproblem.php?pid=6069php

題目大意:求 i 從 l 到 r 中 i 的k次方的因子數之和。ios

解題思路:咱們能夠知道一個數有因子,則這個數的因子必定是若干個質數因子排列組合獲得的。咱們首先要獲得10^6中的素數,而後它的因子數量是 相同質因子數量+1 的乘積,因此咱們可以想到從 l 到 r 枚舉每個i獲得其 相同質因子數量+1 的乘積 的累加和。可是這樣在枚舉時會發現有一些質數是並非所求的 i 的因子,因此咱們應該反過來考慮,對於每個質因子找出 l 到 r 中它的倍數,這樣時間就被縮短了。c++

AC代碼:spa

 1 #include <iostream>
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 const int maxn=1100000;
 5 const long long SMod=998244353;
 6 bool is_prime[maxn+1];
 7 long long  prime[maxn],tmp[maxn],in[maxn];
 8 int sieve(int n)
 9 {
10     int p=0;
11     for(int i=0; i<=n; i++) is_prime[i]=true;
12     is_prime[0]=is_prime[1]=false;
13     for(int i=2; i<=n; i++)
14     {
15         if(is_prime[i])
16         {
17             prime[p++]=i;
18             for(int j=2*i; j<=n; j=j+i)
19                 is_prime[j]=false;
20         }
21     }
22     return p;
23 }
24 int main()
25 {
26     sieve(1000007);
27 //    for(int i=0;i<10;i++)
28 //    printf("%d\n",prime[i]);
29     //freopen("1003.in","r",stdin);
30     //freopen("out.txt","w",stdout);
31     int t;
32     long long l,r,k,ans,cnt,num;
33     scanf("%d",&t);
34     while(t--)
35     {
36         scanf("%lld%lld%lld",&l,&r,&k);
37         int len=r-l;
38         for(int i=0; i<=len; i++)
39         {
40             tmp[i]=1;
41             in[i]=i+l;
42         }
43         ans=0;
44         num=0;
45         for(int i=0; prime[i]*prime[i]<=r&&i<78498; i++)
46         {
47             int p=prime[i];
48             for(int j=l/p*p-l; j<=len; j+=p)
49             {
50                 if(j<0)
51                     continue;
52                 num=0;
53                 while(in[j]%p==0)
54                 {
55                     num++;
56                     in[j]=in[j]/p;
57                 }
58                 tmp[j]=(tmp[j]*(((num*k)%SMod)+1))%SMod;
59             }
60         }
61         for(int i=0; i<=len; i++)
62         {
63             if(in[i]>1)
64                 tmp[i]=(tmp[i]*(k+1))%SMod;
65             //printf("%lld %lld %lld\n",in[i],l+i,tmp[i]);
66             ans=(ans+tmp[i])%SMod;
67             //printf("%lld\n",ans);
68         }
69         printf("%lld\n",ans);
70     }
71     return 0;
72 }

 

 

這個代碼挺奇怪的我感受都對,可是15個數據過了14個就倒數第二個錯了鬱悶啊>_<||| 。code

求大神指點一下blog

 1 #include <iostream>
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 const int maxn=1100000;
 5 const long long SMod=998244353;
 6 bool is_prime[maxn+1];
 7 long long  prime[maxn],tmp[maxn],in[maxn];
 8 int sieve(int n)
 9 {
10     int p=0;
11     for(int i=0; i<=n; i++) is_prime[i]=true;
12     is_prime[0]=is_prime[1]=false;
13     for(int i=2; i<=n; i++)
14     {
15         if(is_prime[i])
16         {
17             prime[p++]=i;
18             for(int j=2*i; j<=n; j=j+i)
19                 is_prime[j]=false;
20         }
21     }
22     return p;
23 }
24 int main()
25 {
26     sieve(1000007);
27 //    for(int i=0;i<10;i++)
28 //    printf("%d\n",prime[i]);
29     //freopen("1003.in","r",stdin);
30     //freopen("out.txt","w",stdout);
31     int t;
32     long long l,r,k,ans,cnt,num;
33     scanf("%d",&t);
34     while(t--)
35     {
36         scanf("%lld%lld%lld",&l,&r,&k);
37         int len=r-l;
38         for(int i=0; i<=len; i++)
39         {
40             tmp[i]=1;
41             in[i]=1;
42         }
43         ans=0;
44         num=0;
45         for(int i=0; prime[i]*prime[i]<=r&&i<78498; i++)
46         {
47             int p=prime[i];
48             int it=prime[i]-(l%prime[i]);
49             if(it==prime[i])
50                 it=0;
51             if(it>len)
52             continue;
53             for(int j=it; j<=len;)
54             {
55                 long long data=j+l;
56                 while(data%p==0)
57                 {
58                     num++;
59                     data=data/p;
60                     in[j]=in[j]*p;
61                 }
62                 if(num!=0)
63                 {
64                     tmp[j]=(tmp[j]*(((num*k)%SMod)+1))%SMod;
65                     num=0;
66                 }
67                 j=j+p;
68             }
69         }
70         for(int i=0; i<=len; i++)
71         {
72             if(in[i]*in[i]<i+l)
73             tmp[i]=tmp[i]*(k+1);
74             //printf("%lld %lld %lld\n",in[i],l+i,tmp[i]);
75             if(l+i==1)
76             {
77                 ans=(ans+1)%SMod;
78             }
79             else if(tmp[i]==1)
80             {
81                 ans=(ans+2)%SMod;
82             }
83             else
84             {
85                 ans=(ans+tmp[i])%SMod;
86             }
87         }
88         printf("%lld\n",ans);
89     }
90     return 0;
91 }
相關文章
相關標籤/搜索