看了網上眾多部落格後,我才發現,實現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 }
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 }
3.loj6035(目前不知為何會爆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 }
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 }
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 }
ATTENTION:篩的質數個數一定要開大一點!不然可能會有一些特別的邊界來卡掉。