很好的学习博客:
http://jiruyi910387714.is-programmer.com/posts/195270.html
https://blog.csdn.net/skywalkert/article/details/50500009
适用范围:
积性(完全积性)函数前缀和,狄利克雷卷积前缀和
套路:
假设现在求f的前缀和:
公式为:
也就是构造h,g使得 h=f*g 其中h的前缀和好求 假设我们要求的是f=μ
怎么构造? 注意到 μ*I=e I(n)=1 e(n)=[n==1] e的前缀和好求,所以h=e,e=I
h(n)前缀和=1,g(i)=1,带入上面的公式即可
注意:
小规模打表,大规模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);
}
}