很好的学习博客:
http://jiruyi910387714.is-programmer.com/posts/195270.html
https://blog.csdn.net/skywalkert/article/details/50500009
适用范围:
积性(完全积性)函数前缀和,狄利克雷卷积前缀和
注意:
小规模打表,大规模map记忆化,取模
关键点就是卷积哪个函数方便求和
刷题:
51nod1244
题意:
莫比乌斯函数前缀和1e10
#include<bits/stdc++.h> #include <hash_map> #include<tr1/unordered_map> using namespace std; using namespace std::tr1; #define ll long long const int maxn=4600005; int mu[maxn]; int pri[1000005]; bool isp[maxn]; map<ll,ll>mp; void init(int n) { mu[1]=1;int p=0; for(int i=2;i<=n;i++) { if(isp[i]==0)mu[i]=-1,pri[++p]=i; for(int j=1;j<=p&&i*pri[j]<=n;j++) { isp[i*pri[j]]=1; if(i%pri[j]==0) { mu[i*pri[j]]=0; break; } else mu[i*pri[j]]=mu[i]*-1; } mu[i]+=mu[i-1]; } } ll dfs(ll x) { if(x<4600002)return mu[x]; if(mp[x])return mp[x]; ll nxt=0; ll res=1; for(ll i=2;i<=x;i=nxt+1) { nxt=x/(x/i); res-=dfs(x/i)*(nxt-i+1); if(nxt==x)break; } mp[x]=res; return res; } int main() { ll a,b; cin>>a>>b; init(min(1ll*4600000,b)); cout<<dfs(b)-dfs(a-1); puts(""); }
hdu5608 这题我会w
题意:
f 狄利克雷卷积 I =n*2-3*n+2 n<1e9,求f前缀和,I(i)=1
思路:
仔细看上面的学习博客
预处理就是枚举d筛掉d的倍数
预处理那块也可以莫比乌斯反演后枚举d
f*I=g => f*I*miu=g*miu => f*e=g*miu => f(n)=sigma( g(d)*miu(n/d) [d|n] )
#include<iostream> #include<stdio.h> #include<map> #define ll long long //#include<tr1/unordered_map> using namespace std; //using namespace std::tr1; const int maxn=1e6+5; const int mod=1e9+7; ll f[maxn]; void init(int n) { for(int i=1;i<=n;i++)f[i]=(1ll*i*i-3*i+2+mod)%mod; for(int i=2;i<=n;i++) for(int j=2*i;j<=n;j+=i) f[j]=(f[j]-f[i]+mod)%mod; for(int i=2;i<=n;i++)f[i]+=f[i-1]%mod,f[i]%=mod; } ll inv(ll t, ll p) { return t == 1 ? 1 : (p - p / t) * inv(p % t, p) % p; } map<ll,ll>mp; ll inv6; ll inv2=500000004; ll get(ll x) { ll sum=2*x; ll t=x*(x+1)%mod*(2*x+1)%mod; t=t*inv6%mod; sum=(sum+t+mod)%mod; t=(3*x*(x+1)%mod)*inv2%mod; sum=(sum-t+mod)%mod; return sum%mod; } ll dfs(ll x) { if(x<=maxn-1)return f[x]; if(mp[x]) return mp[x]; ll res= get(x);ll nxt=0; for(int i=2;i<=x;i=nxt+1) { nxt=x/(x/i); res=(res-(dfs(x/i)*(nxt-i+1)%mod)+mod)%mod; } return mp[x]=(res%mod); } int main() { int T;inv6=inv(6,mod); init(maxn-1);ll n; cin>>T; // cout<<f[123400]<<endl; while(T--) { scanf("%I64d",&n); printf("%I64d\n",dfs(n)%mod); } }
第二种预处理
#include<iostream> #include<stdio.h> #include<map> #include<string.h> //#include<tr1/unordered_map> using namespace std; //using namespace std::tr1; #define ll long long const int maxn=1e6+5; const int mod=1e9+7; ll f[maxn]; int pri[500005]; bool isp[maxn]; ll mu[maxn]; void init(int n) { int p=0;mu[1]=1; for(int i=2;i<=n;i++) { if(isp[i]==0) pri[++p]=i,mu[i]=-1; for(int j=1;j<=p&&pri[j]*i<=n;j++) { isp[i*pri[j]]=1; if(i%pri[j]==0) { mu[i*pri[j]]=0; break; } else mu[i*pri[j]]=-mu[i]; } } for(ll i=1;i<=n;i++) { for(ll j=1;i*j<=n;j++) f[i*j]+=mu[j]*((i*i-3*i+2+mod)%mod),f[i*j]%=mod; f[i]+=f[i-1]%mod,f[i]=(f[i]+mod)%mod; } } ll inv(ll t, ll p) { return t == 1 ? 1 : (p - p / t) * inv(p % t, p) % p; } map<ll,ll>mp; ll inv6; ll inv2=500000004; ll get(ll x) { ll sum=2*x; ll t=x*(x+1)%mod*(2*x+1)%mod; t=t*inv6%mod; sum=(sum+t+mod)%mod; t=(3*x*(x+1)%mod)*inv2%mod; sum=(sum-t+mod)%mod; return sum%mod; } ll dfs(ll x) { if(x<=maxn-1)return f[x]; if(mp[x]) return mp[x]; ll res= get(x);ll nxt=0; for(int i=2;i<=x;i=nxt+1) { nxt=x/(x/i); res=(res-(dfs(x/i)*(nxt-i+1)%mod)+mod)%mod; } return mp[x]=(res%mod); } int main() { int T;inv6=inv(6,mod); memset(f,0,sizeof(f)); init(maxn-1);ll n; //cout<<f[123400]<<" "<<mu[123400]<<endl; cin>>T; while(T--) { scanf("%I64d",&n); printf("%I64d\n",dfs(n)%mod); } }