看了网上众多博客后,我才发现,实现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.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 }
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:筛的质数个数一定要开大一点!不然可能会有一些特别的边界来卡掉。
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 }
https://www.luogu.org/problemnew/show/P5325