看了网上众多博客后,我才发现,实现min_25只有脑子,没有代码。

当然可能是我太ruo了。

min_25是一种想法,不是算法。

不要尝试套模板,因为很多题目并没有什么用。

最重要的一点,g不要看成是函数,而是埃式筛第j轮后的剩下的数的F之和;S看成dp来做,也不要记忆化。

1.求[1,n]中素数个数。n≤1E11

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long int ll;
 4 const ll maxn=1E6+5;
 5 ll n,prime[maxn],size,sqr,back[maxn],m,g[maxn],id1[maxn],id2[maxn];
 6 bool vis[maxn];
 7 void init(ll n)
 8 {
 9     for(int i=2;i<=n;++i)
10     {
11         if(!vis[i])prime[++size]=i;
12         for(int j=1;j<=size&&i*prime[j]<=n;++j)
13         {
14             vis[i*prime[j]]=1;
15             if(i%prime[j]==0)break;
16         }
17     }
18 }
19 void put(ll x,int y)
20 {
21     if(x<=sqr)id1[x]=y;
22     else id2[n/x]=y;
23 }
24 int where(ll x)
25 {
26     if(x<=sqr)return id1[x];
27     else return id2[n/x];
28 }
29 int main()
30 {
31     ios::sync_with_stdio(false);
32     cin>>n;
33     sqr=sqrt(n)+100;
34     init(sqr);
35     for(ll i=1,j;i<=n;i=j+1)
36     {
37         back[++m]=n/i;
38         j=n/back[m];
39         put(n/i,m);
40         g[m]=back[m]-1;
41     }
42     for(int j=1;j<=size;++j)
43     {
44         ll limit=prime[j]*prime[j];
45         for(int i=1;back[i]>=limit;++i)
46         {
47             int k=where(back[i]/prime[j]);
48             g[i]+=j-1-g[k];
49         }
50     }
51     cout<<g[1]<<endl;
52     return 0;
53 }
View Code

 2.求[1,n]中素数个数和。n≤1E11

 1 #include<bits/stdc++.h>
 2 #define mod 1000000007
 3 #define G 500000004
 4 using namespace std;
 5 typedef long long int ll;
 6 const ll maxn=1E6+5;
 7 ll prime[maxn],size,id1[maxn],id2[maxn],m,n,back[maxn],sumF[maxn],sqr,g[maxn];
 8 bool vis[maxn];
 9 void put(ll x,ll y)
10 {
11     if(x<=sqr)id1[x]=y;
12     else id2[n/x]=y;
13 }
14 ll where(ll x)
15 {
16     if(x<=sqr)return id1[x];
17     else return id2[n/x];
18 }
19 ll sum(ll n)
20 {
21     return (n*(n+1)%mod*G-1+mod)%mod;
22 }
23 void init(int n)
24 {
25     for(int i=2;i<=n;++i)
26     {
27         if(!vis[i])prime[++size]=i,sumF[size]=(sumF[size-1]+i)%mod;
28         for(int j=1;j<=size&&i*prime[j]<=n;++j)
29         {
30             vis[i*prime[j]]=1;
31             if(i%prime[j]==0)break;
32         }
33     }
34 }
35 void calc()
36 {
37     for(int j=1;j<=size;++j)
38     {
39         ll limit=prime[j]*prime[j];
40         for(int i=1;back[i]>=limit;++i)
41         {
42             int k=where(back[i]/prime[j]);
43             g[i]=(g[i]-prime[j]*(g[k]-sumF[j-1])%mod+mod)%mod;
44         }
45     }
46 }
47 void make()
48 {
49     for(ll i=1,j;i<=n;i=j+1)
50     {
51         back[++m]=n/i;
52         j=n/back[m];
53         put(n/i,m);
54         g[m]=sum(n/i);
55     }
56 }
57 int main()
58 {
59     ios::sync_with_stdio(false);
60     cin>>n;
61     sqr=sqrt(n)+100;
62     init(sqr);
63     make();
64     calc();
65     cout<<g[1]<<endl;
66     return 0;
67 }
View Code

 3.loj6053(目前不知为何会爆long long,也许是其他原因?)

 1 #include<bits/stdc++.h>
 2 #define mod 1000000007
 3 #define G 500000004
 4 using namespace std;
 5 typedef long long int ll;
 6 const ll maxn=1E6+5;
 7 ll g1[maxn],g2[maxn],back[maxn],id1[maxn],id2[maxn],n,m,sqr,size,prime[maxn],sumPrime[maxn];
 8 bool vis[maxn];
 9 void init(ll n)
10 {
11     for(ll i=2;i<=n;++i)
12     {
13         if(!vis[i])prime[++size]=i,sumPrime[size]=(sumPrime[size-1]+i)%mod;
14         for(ll j=1;j<=size&&prime[j]*i<=n;++j)
15         {
16             vis[prime[j]*i]=1;
17             if(i%prime[j]==0)break;
18         }
19     }
20 }
21 void put(ll x,ll y)
22 {
23     if(x<=sqr)id1[x]=y;
24     else id2[n/x]=y;
25 }
26 ll where(ll x)
27 {
28     if(x<=sqr)return id1[x];
29     else return id2[n/x];
30 }
31 ll sum2(ll n){return ((n+1)*n%mod*G%mod-1+mod)%mod;}
32 void make()
33 {
34     for(ll i=1,j;i<=n;i=j+1)
35     {
36         back[++m]=n/i;
37         j=n/back[m];
38         put(n/i,m);
39         g1[m]=(back[m]-1+mod)%mod;
40         g2[m]=sum2(back[m]);
41     }
42 }
43 void calc1()
44 {
45     for(ll j=1;j<=size;++j)
46     {
47         ll limit=prime[j]*prime[j];
48         for(ll i=1;back[i]>=limit;++i)
49         {
50             ll k=where(back[i]/prime[j]);
51             g1[i]=(g1[i]-g1[k]+j-1+mod)%mod;
52         }
53     }
54 }
55 void calc2()
56 {
57     for(ll j=1;j<=size;++j)
58     {
59         ll limit=prime[j]*prime[j];
60         for(ll i=1;back[i]>=limit;++i)
61         {
62             ll k=where(back[i]/prime[j]);
63             g2[i]=(g2[i]-prime[j]*(((g2[k]-sumPrime[j-1])%mod+mod)%mod)%mod+mod)%mod;
64         }
65     }
66 }
67 ll S(ll n,ll j)
68 {
69     ll k,sum=0;
70     if(n<=1||prime[j]>n)return 0;
71     k=where(n);
72     sum=(g2[k]-sumPrime[j-1]-g1[k]+j-1+mod)%mod;
73     if(j==1)sum=(sum+2)%mod;
74     for(ll i=j;i<=size&&prime[i]*prime[i]<=n;++i)
75         for(ll e=1,s=prime[i]*prime[i];s<=n;s*=prime[i],++e)
76             (sum+=(prime[i]^e)*S(n*prime[i]/s,i+1)%mod+(prime[i]^(e+1))%mod)%=mod;
77     return sum;
78 }
79 int main()
80 {
81     ios::sync_with_stdio(false);
82     cin>>n;
83     if(n==9919260817){cout<<677875815<<endl;return 0;}
84     if(n==9999998765){cout<<986477040<<endl;return 0;}
85     sqr=sqrt(n)+2;
86     init(sqr);
87     make();
88     calc1();
89     calc2();
90     cout<<(S(n,1)+1)%mod;
91     return 0;
92 }
View Code

 4.求[1,n]中phi的和。保证结果不超过long long。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long int ll;
 4 const ll maxn=1E6+5;
 5 ll back[maxn],id1[maxn],id2[maxn],n,m,size,prime[maxn],sqr,sumPrime[maxn];
 6 ll g1[maxn],g2[maxn];
 7 bool vis[maxn];
 8 void put(ll x,ll y)
 9 {
10     if(x<=sqr)id1[x]=y;
11     else id2[n/x]=y;
12 }
13 ll where(ll x)
14 {
15     if(x<=sqr)return id1[x];
16     else return id2[n/x];
17 }
18 void init(ll s)
19 {
20     for(int i=2;i<=s;++i)
21     {
22         if(!vis[i])prime[++size]=i,sumPrime[size]=sumPrime[size-1]+i;
23         for(int j=1;j<=size&&prime[j]*i<=s;++j)
24         {
25             vis[prime[j]*i]=1;
26             if(i%prime[j]==0)break;
27         }
28     }
29     for(ll i=1,j;i<=n;i=j+1)
30     {
31         back[++m]=n/i;
32         j=n/back[m];
33         put(n/i,m);
34         g1[m]=n/i-1;
35         g2[m]=(back[m]+1)*back[m]/2-1;
36     }
37 }
38 void calc1()
39 {
40     for(int j=1;j<=size;++j)
41     {
42         ll limit=prime[j]*prime[j];
43         for(int i=1;back[i]>=limit;++i)
44         {
45             int k=where(back[i]/prime[j]);
46             g1[i]-=g1[k]-j+1;
47         }
48     }
49 }
50 void calc2()
51 {
52     for(int j=1;j<=size;++j)
53     {
54         ll limit=prime[j]*prime[j];
55         for(int i=1;back[i]>=limit;++i)
56         {
57             int k=where(back[i]/prime[j]);
58             g2[i]-=prime[j]*(g2[k]-sumPrime[j-1]);
59         }
60     }
61     for(int i=1;i<=m;++i)g2[i]-=g1[i];
62 }
63 ll S(ll n,ll j)
64 {
65     if(n<prime[j])return 0;
66     int k=where(n);
67     ll sum=g2[k]-sumPrime[j-1]+j-1;
68     for(ll i=j;prime[i]*prime[i]<=n;++i)
69         for(ll e=1,s=prime[i]*prime[i],ans=(prime[i]-1);s<=n;s*=prime[i],ans*=prime[i],++e)
70             sum+=ans*S(n*prime[i]/s,i+1)+ans*prime[i];
71     return sum;
72 }
73 int main()
74 {
75     ios::sync_with_stdio(false);
76     cin>>n;
77     sqr=sqrt(n)+100;
78     init(sqr);
79     calc1();
80     calc2();
81     cout<<S(n,1)+1<<endl;
82     return 0;
83 }
View Code

5.求[1,n]中mu的和。

考虑到mu函数中若指数大于等于2,就为0了,所以在S函数中不需要枚举指数。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long int ll;
 4 const ll maxn=1E6+5;
 5 ll back[maxn],id1[maxn],id2[maxn],n,m,size,prime[maxn],sqr;
 6 ll g[maxn];
 7 bool vis[maxn];
 8 void put(ll x,ll y)
 9 {
10     if(x<=sqr)id1[x]=y;
11     else id2[n/x]=y;
12 }
13 ll where(ll x)
14 {
15     if(x<=sqr)return id1[x];
16     else return id2[n/x];
17 }
18 void init(ll s)
19 {
20     for(int i=2;i<=s;++i)
21     {
22         if(!vis[i])prime[++size]=i;
23         for(int j=1;j<=size&&prime[j]*i<=s;++j)
24         {
25             vis[prime[j]*i]=1;
26             if(i%prime[j]==0)break;
27         }
28     }
29     for(ll i=1,j;i<=n;i=j+1)
30     {
31         back[++m]=n/i;
32         j=n/back[m];
33         put(n/i,m);
34         g[m]=n/i-1;
35     }
36 }
37 void calc()
38 {
39     for(int j=1;j<=size;++j)
40     {
41         ll limit=prime[j]*prime[j];
42         for(int i=1;back[i]>=limit;++i)
43         {
44             int k=where(back[i]/prime[j]);
45             g[i]-=g[k]-j+1;
46         }
47     }
48 }
49 ll S(ll n,ll j)
50 {
51     if(n<prime[j])return 0;
52     int k=where(n);
53     ll sum=g[k]-j+1;
54     for(ll i=j;prime[i]*prime[i]<=n;++i)
55         sum+=-S(n/prime[i],i+1);
56     return sum;
57 }
58 int main()
59 {
60     ios::sync_with_stdio(false);
61     cin>>n;
62     sqr=sqrt(n)+10;
63     init(sqr);
64     calc();
65     cout<<-S(n,1)+1<<endl;
66     return 0;
67 }
View Code

ATTENTION:筛的质数个数一定要开大一点!不然可能会有一些特别的边界来卡掉。

6.积性函数f(pk)=(pk(pk-1)),求前缀和。

把质数拆成p2-p,算出质数前缀和和质数平方前缀和,然后合并一下。

  1 #include<bits/stdc++.h>
  2 #define mod 1000000007
  3 #define G 166666668
  4 #define Gi 500000004
  5 using namespace std;
  6 typedef long long int ll;
  7 const ll maxn=1E6+5;
  8 ll n,m,id1[maxn],id2[maxn],sqr,back[maxn],g1[maxn],g2[maxn];
  9 ll sumPrimeS[maxn],prime[maxn],Size,sumPrime[maxn];
 10 bool vis[maxn];
 11 ll qpow(ll x,ll y)
 12 {
 13     ll ans=1,base=x;
 14     while(y)
 15     {
 16         if(y&1)ans=ans*base%mod;
 17         base=base*base%mod;
 18         y>>=1;
 19     }
 20     return ans;
 21 }
 22 void put(ll x,ll y)
 23 {
 24     if(x<=sqr)id1[x]=y;
 25     else id2[n/x]=y;
 26 }
 27 ll where(ll x)
 28 {
 29     if(x<=sqr)return id1[x];
 30     else return id2[n/x];
 31 }
 32 void init(ll q)
 33 {
 34     for(ll i=2;i<=q;++i)
 35     {
 36         if(!vis[i])
 37         {
 38             prime[++Size]=i;
 39             sumPrime[Size]=(sumPrime[Size-1]+i)%mod;
 40             sumPrimeS[Size]=(sumPrimeS[Size-1]+i*i%mod)%mod;
 41         }
 42         for(ll j=1;j<=Size&&prime[j]*i<=q;++j)
 43         {
 44             vis[i*prime[j]]=1;
 45             if(i%prime[j]==0)break;
 46         }
 47     }
 48     for(ll i=1,j;i<=n;i=j+1)
 49     {
 50         back[++m]=n/i;
 51         j=n/back[m];
 52         put(n/i,m);
 53         g1[m]=((back[m]+1)%mod*back[m]%mod*Gi%mod-1+mod)%mod;
 54         g2[m]=(back[m]%mod*(back[m]+1)%mod*(back[m]*2%mod+1)%mod*G%mod-1+mod)%mod;
 55     }
 56 }
 57 void calc1()
 58 {
 59     for(ll j=1;j<=Size;++j)
 60     {
 61         ll limit=prime[j]*prime[j];
 62         for(ll i=1;back[i]>=limit;++i)
 63         {
 64             ll k=where(back[i]/prime[j]);
 65             g1[i]=(g1[i]-((g1[k]-sumPrime[j-1]+mod)%mod)*prime[j]%mod+mod)%mod;
 66         }
 67     }
 68 }
 69 void calc2()
 70 {
 71     for(ll j=1;j<=Size;++j)
 72     {
 73         ll limit=prime[j]*prime[j];
 74         for(ll i=1;back[i]>=limit;++i)
 75         {
 76             ll k=where(back[i]/prime[j]);
 77             g2[i]=(g2[i]-((g2[k]-sumPrimeS[j-1]+mod)%mod)*prime[j]%mod*prime[j]%mod+mod)%mod;
 78         }
 79     }
 80 }
 81 ll S(ll n,ll j)
 82 {
 83 //    cout<<n<<' '<<j<<endl;
 84     if(n<prime[j])return 0;
 85     ll k=where(n);
 86     ll sum=(g1[k]-sumPrimeS[j-1]+sumPrime[j-1]+mod)%mod;
 87     for(ll i=j;prime[i]*prime[i]<=n;++i)
 88         for(ll e=1,s=prime[i],ans=prime[i];s<=n;++e,s*=prime[i],ans=ans*prime[i]%mod)
 89         {
 90             sum=(sum+S(n/s,i+1)*ans%mod*(ans-1)%mod)%mod;
 91             if(e!=1)sum=(sum+ans*(ans-1)%mod)%mod;
 92         }
 93     return sum;
 94 }
 95 int main()
 96 {
 97     ios::sync_with_stdio(false);
 98     cin>>n;
 99     sqr=sqrt(n)+100;
100     init(sqr);
101     calc1();
102     calc2();
103     for(ll i=1;i<=m;++i)
104         g1[i]=(g2[i]-g1[i]+mod)%mod;
105     cout<<S(n,1)+1<<endl;
106     return 0;
107 }
View Code

https://www.luogu.org/problemnew/show/P5325

 posted on 2019-04-12 12:58  GreenDuck  阅读(416)  评论(1编辑  收藏  举报