# 各种反演细节梳理&模板

stO FDF Orz（证明全有%%%）

## 莫比乌斯反演

$$F(n)=\sum\limits_{d|n}f(d)\Rightarrow f(n)=\sum\limits_{d|n}\mu(\frac n d)F(d)$$
$$F(n)=\sum\limits_{n|d}f(d)\Rightarrow f(n)=\sum\limits_{n|d}\mu(\frac d n)F(d)$$

$$[\gcd(i,j)==1]=\sum\limits_{d|gcd(i,j)}\mu(d)$$
$$gcd(i,j)=\sum\limits_{d|i,d|j}\varphi(d)$$

$$f(n)=\sum\limits_{i=1}^a\sum\limits_{j=1}^b[\gcd(i,j)==n]$$
1.老实反演
$$F(n)=\sum\limits_{n|d}f(d)=\lfloor\frac a n\rfloor\lfloor\frac b n\rfloor$$
$$f(n)=\sum\limits_{n|d}\mu(\frac{d}{n})\lfloor\frac{a}{d}\rfloor\lfloor\frac{b}{d}\rfloor=\sum\limits_{d=1}^{\lceil\frac{\min(a,b)}{n}\rceil}\mu(d)\lfloor\frac a{nd}\rfloor\lfloor\frac b{nd}\rfloor$$
2.套式子
$$f(n)=\sum\limits_{i=1}^{\lfloor\frac{a}{n}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{b}{n}\rfloor}[\gcd(i,j)==1]=\sum\limits_{d|gcd(i,j)}\sum\limits_{i=1}^{\lfloor\frac{a}{n}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{b}{n}\rfloor}\mu(d)=\sum\limits_{d=1}^{\lfloor\frac{\min(a,b)}{n}\rfloor}\mu(d)\lfloor\frac a{nd}\rfloor\lfloor\frac b{nd}\rfloor$$

#include<bits/stdc++.h>
#define LL long long
#define RG register
#define R RG int
using namespace std;
const int SZ=1<<19,N=50009;
int u[N],pr[N],p;bool f[N];
char buf[SZ],*ie=buf+SZ,*ip=ie-1;
inline int in(){
G;while(*ip<'-')G;
R x=*ip&15;G;
while(*ip>'-'){x*=10;x+=*ip&15;G;}
return x;
}
int main(){
u[1]=f[1]=1;
for(R i=2;i<N;++i){
if(!f[i])u[pr[++p]=i]=-1;
for(R j=1;j<=p&&i*pr[j]<N;++j){
f[i*pr[j]]=1;
if(i%pr[j]==0)break;
u[i*pr[j]]=-u[i];
}
u[i]+=u[i-1];
}
for(R n=in();n;--n){
R a=in(),b=in(),d=in(),lim=min(a,b)/d,ans=0;
for(R l=1,r;l<=lim;l=r+1){
r=min(a/(a/l),b/(b/l));
ans+=(u[r]-u[l-1])*(a/(d*l))*(b/(d*l));
}
printf("%d\n",ans);
}
return 0;
}


$\sum_{i=1}^n\sum_{j=1}^m\frac{ij}{\gcd(i,j)}\\=\sum_{k=1}^n\sum_{i=1}^n\sum_{j=1}^m\frac{ij}{k}[\gcd(i,j)==k]\\=\sum_{k=1}^n\sum_{i=1}^\frac{n}{k}\sum_{j=1}^\frac{m}{k}ijk[\gcd(i,j)==1]\\=\sum_{k=1}^nk\cdot\sum_{i=1}^\frac{n}{k}\sum_{j=1}^\frac{m}{k}\sum_{d|\gcd(i,j)}\mu(d)ij\\=\sum_{k=1}^nk\cdot\sum_{d=1}^\frac{n}{k}\mu(d)\sum_{i=1}^\frac{n}{kd}\sum_{j=1}^\frac{m}{kd}d^2ij\\=\sum_{k=1}^nk\cdot\sum_{d=1}^\frac{n}{k}d^2\mu(d)\frac{\frac{n}{kd}(\frac{n}{kd}+1)}{2}\frac{\frac{m}{kd}(\frac{m}{kd}+1)}{2}$

#include<bits/stdc++.h>
#define LL long long
#define RG register
#define R RG int
#define YL 20101009
using namespace std;
const int N=1e7+9;
int p,pr[N/10],mu[N],s[N];bitset<N>np;
inline LL Sum(LL x){
return x*(x+1)%YL*((YL+1)>>1)%YL;
}
LL Calc(R n,R m){
LL ans=0;
for(R d=1,r;d<=n;d=r+1){
r=min(n/(n/d),m/(m/d));
ans=(ans+(s[r]-s[d-1]+YL)*Sum(n/d)%YL*Sum(m/d))%YL;
}
return ans;
}
int main(){
R n,m;LL ans=0;
cin>>n>>m;
if(n>m)swap(n,m);
s[1]=1;
for(R i=2;i<=n;++i){
if(!np[i])pr[++p]=i,mu[i]=-1;
s[i]=(s[i-1]+(LL)i*i%YL*mu[i]+YL)%YL;
for(R j=1;j<=p&&i*pr[j]<=n;++j){
np[i*pr[j]]=1;
if(i%pr[j]==0)break;
mu[i*pr[j]]=-mu[i];
}
}
for(R k=1,r;k<=n;k=r+1){
r=min(n/(n/k),m/(m/k));
ans=(ans+(Sum(r)-Sum(k-1)+YL)*Calc(n/k,m/k))%YL;
}
cout<<ans<<endl;
return 0;
}


$\sum_{t=1}^n\frac{\frac{n}{t}(\frac{n}{t}+1)}{2}\frac{\frac{m}{t}(\frac{m}{t}+1)}{2}\sum_{d|t}td\mu(d)$

$\prod\limits_{i=1}^n\prod\limits_{j=1}^mFib_{\gcd(i,j)}=\prod\limits_{k=1}^nFib_k^{\sum\limits_{d=1}^n\mu(d)\frac{n}{kd}\frac{m}{kd}}=\prod\limits_{t=1}^n\prod\limits_{k|t}Fib_k^{\mu(\frac{t}{k})\frac{n}{t}\frac{m}{t}}\\=\prod\limits_{t=1}^n\left(\prod\limits_{k|t}Fib_k^{\mu(\frac{t}{k})}\right)^{\frac{n}{t}\frac{m}{t}}$

## 二项式反演

### 错排

$$f(n)$$为至多$$n$$元素错排方案数也就是全排列方案数$$n!$$$$g(n)$$$$n$$元素错排方案数。

### 又一个例题

#include<bits/stdc++.h>
#define LL long long
#define RG register
#define R RG int
using namespace std;
const LL N=2009,YL=1e9+9;
int a[N],b[N],ff[N],gg[N],F[N],I[N];
int Pow(LL b,R k,LL a=1){
for(;k;k>>=1,b=b*b%YL)
if(k&1)a=a*b%YL;
return a;
}
int main(){
R n,k,ans=0,*f=ff,*g=gg;
cin>>n>>k;k=(n+k)/2;
for(R i=1;i<=n;++i)cin>>a[i];
for(R i=1;i<=n;++i)cin>>b[i];
sort(a+1,a+n+1);
sort(b+1,b+n+1);
f[0]=g[0]=F[0]=1;
for(R i=1;i<=n;++i){
R pos=lower_bound(b+1,b+n+1,a[i])-b-1;
for(R j=1;j<=i;++j)
g[j]=(f[j]+(LL)f[j-1]*max(pos-j+1,0))%YL;
swap(f,g);
}
for(R i=1;i<=n;++i)F[i]=(LL)F[i-1]*i%YL;
I[n]=Pow(F[n],YL-2);
for(R i=n;i;--i)I[i-1]=(LL)I[i]*i%YL;
for(R i=k;i<=n;++i)
ans=(ans+(LL)((i-k)&1?YL-1:1)*F[i]%YL*I[k]%YL*I[i-k]%YL*F[n-i]%YL*f[i])%YL;
cout<<ans<<endl;
return 0;
}


## 斯特林反演

BZOJ4671 异或图

#include<bits/stdc++.h>
#define LL long long
#define RG register
#define R RG int
using namespace std;
const int S=69,N=19;
char str[S];bool g[S][N][N];
int s,n,c[N];
LL ans,lb[S],fac[N];
void calc(R t){
R cnt=0;memset(lb,0,sizeof(lb));
for(R k=1;k<=s;++k){
R p=0;LL now=0;
for(R i=1;i<=n;++i)
for(R j=i+1;j<=n;++j)
if(c[i]!=c[j])now|=(LL)g[k][i][j]<<p++;
for(R i=0;i<p;++i)
if(1ll<<i&now){
if(lb[i])now^=lb[i];
else{lb[i]=now;++cnt;break;}
}
}
ans+=(1&t?1:-1)*fac[t-1]*(1ll<<(s-cnt));
}
void dfs(R x,R t){
if(x>n)return calc(t-1);
for(R&i=c[x]=1;i<=t;++i)dfs(x+1,t+(t==i));
}
int main(){
cin>>s;
for(R k=1;k<=s;++k){
cin>>str;n=(1+sqrt(1+8*strlen(str)))/2;
for(R i=1,p=0;i<=n;++i)
for(R j=i+1;j<=n;++j)
g[k][i][j]=str[p++]&1;
}
for(R i=fac[0]=1;i<=n;++i)fac[i]=fac[i-1]*i;
dfs(1,1);
cout<<ans<<endl;
return 0;
}


## 最值反演（min-max容斥）

$$\max\{S\}=\sum\limits_{T\subseteq S}(-1)^{|T|+1}\min\{T\}$$
$$\min\{S\}=\sum\limits_{T\subseteq S}(-1)^{|T|+1}\max\{T\}$$

$$E(\max\{S\})=\sum\limits_{T\subseteq S}(-1)^{|T|+1}E(\min\{T\})$$
$$E(\min\{S\})=\sum\limits_{T\subseteq S}(-1)^{|T|+1}E(\max\{T\})$$

$$\max_k\{S\}=\sum\limits_{T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}\min\{T\}$$
$$\min_k\{S\}=\sum\limits_{T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}\max\{T\}$$

#include<bits/stdc++.h>
#define R register int
using namespace std;
double EPS=1e-10,a[1<<20];
int c[1<<20];
int main(){
R n,m,s=0;
cin>>n;m=1<<n;
for(R i=0;i<m;++i){
cin>>a[i];
if(a[i]>EPS)s|=i;
c[i]=c[i>>1]^(1&i);
}
if(s!=m-1)return puts("INF"),0;
for(R i=1;i<m;i<<=1)
for(R j=0;j<m;j+=i<<1)
for(R k=0;k<i;++k)
a[k+j+i]+=a[k+j];
double ans=0;
for(R i=1;i<m;++i)
if(a[i]>EPS)ans+=(c[i]?1:-1)/(1-a[i^(m-1)]);
return printf("%.10lf\n",ans),0;
}


#include<bits/stdc++.h>
#define LL long long
#define RG register
#define R RG int
using namespace std;
const int SZ=1<<19,N=10009,YL=998244353;
char buf[SZ],*ie=buf+SZ,*ip=ie-1;
int f[N][12];LL inv[N];
inline int in(){
G;while(*ip<'-')G;
R x=*ip&15;G;
while(*ip>'-'){x*=10;x+=*ip&15;G;}
return x;
}
inline int add(R x,R y){static int z;z=x+y;return z<YL?z:z-YL;}
inline int sub(R x,R y){static int z;z=x-y;return z<0?z+YL:z;}
int main(){
R n=in(),s=n-in()+1,m=in();
f[0][0]=1;
for(R i=1;i<=n;++i){
R p=in();
for(R j=m-p;~j;--j)
for(R k=s;k;--k)
}
inv[1]=1;LL ans=f[1][s];
for(R i=2;i<=m;++i){
inv[i]=(YL-YL/i)*inv[YL%i]%YL;
ans=(ans+f[i][s]*inv[i])%YL;
}
cout<<ans*m%YL<<endl;
return 0;
}


## 子集反演

$$\mu(S)=(-1)^{|S|}[S中没有重复元素]$$
（原来莫比乌斯函数就是把整数看作其质因数集合而得来的反演系数啊）
$$f(S)=\sum\limits_{T\subseteq S}g(T)\Rightarrow g(S)=\sum\limits_{T\subseteq S}\mu(S-T)f(T)$$
$$f(S)=\sum\limits_{S\subseteq T}g(T)\Rightarrow g(S)=\sum\limits_{S\subseteq T}\mu(T-S)f(T)$$

## 单位根反演

posted @ 2019-01-26 16:46  Flash_Hu  阅读(1032)  评论(2编辑  收藏  举报