1.积性函数和完全积性函数
积性函数:f(ab)=f(a)f(b) 当(a,b)=1 如μ,φ
完全积性函数:f(ab)=f(a)f(b) 如1,id,idk(i的k次幂),e
定义:1(x)=x,e(x)=[x==1],id(x)=x
公式:(1).(求gcd常用)1*μ=e
(2).μ*id=φ
(3).1*φ=1*μ*id=e*id=id
2.线性筛
Trick:积性函数f,g的积h(x)=f(x)g(x)也是积性函数,可以用线性筛处理。
3.莫比乌斯反演
利用1*μ=e,所以若有F=1*f,则f=e*f=μ*1*f=μ*F
Trick1:F(n)=∑n|d f(d),则f(n)=∑n|d μ(d/n)*F(d)
Trick2:求前缀和,数论分块
luoguP1829 [国家集训队]Crash的数字表格 / JZPTAB

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int N=10000010,mod=20101009; 5 int cc,vis[N],pr[N],sm[N];//sum of miu(i)*i*i 6 ll n,m,ans; 7 inline void init() 8 { 9 vis[1]=1;sm[1]=1; 10 for(int i=2;i<N;i++) 11 { 12 if(!vis[i])pr[++cc]=i,sm[i]=-1; 13 for(int j=1;j<=cc&&1ll*i*pr[j]<N;j++) 14 { 15 vis[i*pr[j]]=1; 16 if(i%pr[j]==0){sm[i*pr[j]]=0;break;} 17 sm[i*pr[j]]=-sm[i]; 18 } 19 } 20 for(int i=1;i<N;i++)sm[i]=(sm[i-1]+1ll*i*i*sm[i])%mod; 21 } 22 inline ll S(ll x){x%=mod;return x*(x+1)%mod*(mod+1)/2%mod;} 23 inline ll F(int x,int y) 24 { 25 ll r=0; 26 for(int i=1,j;i<=x;i=j+1) 27 { 28 j=min(x/(x/i),y/(y/i)); 29 r+=S(x/i)*S(y/i)%mod*(sm[j]-sm[i-1])%mod; 30 } 31 return r; 32 } 33 int main() 34 { 35 scanf("%lld%lld",&n,&m);init(); 36 if(n>m)swap(n,m); 37 for(int i=1,j;i<=n;i=j+1) 38 { 39 j=min(n/(n/i),m/(m/i)); 40 ans+=F(n/i,m/i)*(S(j)-S(i-1))%mod; 41 } 42 printf("%d ",(ans%mod+mod)%mod); 43 return 0; 44 }
启发:类似的问题通过固定一个元的变化观察式子剩下部分变化的规律(如是否有大量连续相同值)。
基础习题:bzoj 2154 bzoj2005 bzoj1101 bzoj 2440
较难的题:bzoj 3529 bzoj 3309 bzoj 3561
模型不明显的题:bzoj 3481 #346. 【Jiangsu Training Contest 8】01 串
***注意复习 估计现在一个都不会了
***注意讨论不同的情况
4.狄利克雷卷积 f*g=∑d|n f(d)g(n/d)
bzoj 4407

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define R register 5 const int N=3005,mod=1000000007; 6 const int pr[]={2,3,5,7,11,13,23,31}; 7 int cc,C[N][N],bnl[N],t[N][N],q[70];ll p[70]; 8 inline int pw(int a,int b){int r=1;a%=mod;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)r=1ll*r*a%mod;return r;} 9 ll mult(ll x,ll y,ll z){return (x*y-(ll)(((long double)x*y+0.5)/(long double)z)*z+z)%z;} 10 inline ll pww(ll a,ll b,ll m){ll r=1;a%=m;for(;b;b>>=1,a=mult(a,a,m))if(b&1)r=mult(r,a,m);return r;} 11 inline void init() 12 { 13 for(int i=0;i<N;i++)C[i][0]=1; 14 for(int i=1;i<N;i++)for(int j=1;j<=i;j++)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; 15 bnl[0]=1; 16 for(R int i=1;i<N-1;i++) 17 { 18 int s=0; 19 for(R int j=0;j<i;j++)s=(s+1ll*C[i+1][j]*bnl[j])%mod; 20 bnl[i]=1ll*pw(i+1,mod-2)*(mod-s)%mod; 21 } 22 for(int i=0;i<=3000;i++) 23 { 24 int iv=pw(i+1,mod-2); 25 for(int j=0;j<=i;j++)t[i][i+1-j]=1LL*bnl[j]*C[i+1][j]%mod*iv%mod; 26 t[i][i]++; 27 } 28 } 29 inline bool miller_rabin(ll n) 30 { 31 if(n==2||n==3||n==5||n==7||n==11||n==13||n==23||n==31)return true; 32 if((n&1)==0)return false; 33 ll r=n-1;int k=0; 34 while((r&1)==0)r>>=1,k++; 35 for(R int i=0;i<8;i++) 36 { 37 ll x=pww(pr[i],r,n),y; 38 for(R int i=0;i<k;i++) 39 { 40 y=mult(x,x,n); 41 if(y==1&&x!=1&&x!=n-1)return 0; 42 x=y; 43 } 44 if(y!=1)return 0; 45 } 46 return 1; 47 } 48 #define Func(x) mult(x,x,n)+1 49 inline int rnd(){return (rand()<<15)^rand();} 50 ll div(ll n) 51 { 52 ll x=rnd()%n+1,y=Func(x); 53 while(x!=y) 54 { 55 ll k=__gcd(n,(y-x+n)%n); 56 if(k!=1&&k!=n)return k; 57 x=Func(x),y=Func(Func(y)); 58 } 59 return -1; 60 } 61 void pollard_rho(ll n) 62 { 63 while(n%2==0){p[++cc]=2;n>>=1;} 64 if(n==1)return; 65 if(miller_rabin(n)){p[++cc]=n;return;} 66 ll x; 67 do x=div(n);while(x==-1); 68 pollard_rho(x);pollard_rho(n/x); 69 } 70 ll n;int x,y; 71 inline int calc(int t,int p,int k) 72 { 73 ll ans=0;int x1=x-t; 74 if(x1<0)x1+=mod-1; 75 x1=pw(p,x1);int x2=pw(p,k*t); 76 for(R int q=0;q<=k;q++)ans+=x2,x2=1ll*x2*x1%mod; 77 x2=pw(p,y+(k-1)*t); 78 for(R int q=0;q<k;q++)ans-=x2,x2=1ll*x2*x1%mod; 79 ans%=mod;return ans<0?ans+mod:ans; 80 } 81 int main() 82 { 83 srand(time(0)); 84 int T;scanf("%d",&T);init(); 85 while(T--) 86 { 87 scanf("%lld%d%d",&n,&x,&y); 88 if(n==1){puts("1");continue;} 89 cc=0;pollard_rho(n);ll ans=0; 90 sort(p+1,p+cc+1);cc=unique(p+1,p+cc+1)-p-1; 91 for(R int i=1;i<=cc;i++) 92 { 93 ll t=n;q[i]=0; 94 while(t%p[i]==0)q[i]++,t/=p[i]; 95 if(p[i]>=mod)p[i]%=mod; 96 } 97 for(R int i=1;i<=y+1;i++) 98 { 99 ll c=t[y][i]; 100 for(int j=1;j<=cc;j++)c=c*calc(i,p[j],q[j])%mod; 101 ans+=c; 102 } 103 ans=ans%mod*pw(n%mod,y)%mod; 104 printf("%lld ",ans); 105 } 106 return 0; 107 }
5.二项式反演
(1).和容斥类似,f(n)=∑C(n,i)gi等价于g(n)=∑(-1)n-iC(n,i)f(i)
(2).少见的:f(k)=∑C(i,k)gi (k<=i<=n)等价于g(k)=∑(-1)i-kC(i,k)f(i) (k<=i<=n)
目前知道的用途:对于不明显的容斥,发现组合数关系可以确定答案一定可以反演回来
6.斯特林数
7.最值反演:MinMax 容斥
topcoder12607RandomPaintingOnABoard
8.FWT
&和|非常简单,可以考虑容斥。xor类似推出运算即可。
9.FMT&子集卷积

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int N=25,M=1<<21|5,mod=998244353; 5 int n,m,p,w[N],fa[N],d[N],e[N][N],pp[N],f[N][M],g[N][M],ok[M],sum[M],inv[M],sz[M]; 6 int pw(int a,int b){int r=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)r=1ll*r*a%mod;return r;} 7 int fnd(int x){return fa[x]?fa[x]=fnd(fa[x]):x;} 8 void fmt(int *a){for(int i=1;i<pp[n];i<<=1)for(int j=0;j<pp[n];j++)if(i&j)a[j]=(a[j]+a[i^j])%mod;} 9 void ifmt(int *a){for(int i=1;i<pp[n];i<<=1)for(int j=0;j<pp[n];j++)if(i&j)a[j]=(a[j]-a[i^j]+mod)%mod;} 10 bool chk(int S) 11 { 12 for(int i=1;i<=n;i++)if(S&pp[i-1])sum[S]+=w[i],sz[S]++,fa[i]=d[i]=0; 13 int b=sz[S]; 14 for(int i=1;i<=n;i++)if(S&pp[i-1])for(int j=i+1;j<=n;j++)if((S&pp[j-1])&&e[i][j]) 15 { 16 d[i]++;d[j]++; 17 if(fnd(i)!=fnd(j))fa[fnd(i)]=fnd(j),b--; 18 } 19 if(b>1)return 1; 20 for(int i=1;i<=n;i++)if((S&pp[i-1])&&(d[i]&1))return 1; 21 return 0; 22 } 23 int main() 24 { 25 scanf("%d%d%d",&n,&m,&p); 26 for(int i=pp[0]=1;i<=25;i++)pp[i]=pp[i-1]*2; 27 for(int i=1,u,v;i<=m;i++)scanf("%d%d",&u,&v),e[u][v]=e[v][u]=1; 28 for(int i=1;i<=n;i++)scanf("%d",&w[i]); 29 for(int i=0;i<pp[n];i++)ok[i]=chk(i); 30 for(int i=0;i<pp[n];i++)sum[i]=pw(sum[i],p),inv[i]=pw(sum[i],mod-2); 31 for(int i=0;i<pp[n];i++)if(ok[i])g[sz[i]][i]=sum[i]; 32 for(int i=0;i<=n;i++)fmt(g[i]); 33 f[0][0]=1;fmt(f[0]); 34 for(int i=1;i<=n;i++) 35 { 36 for(int j=0;j<i;j++)for(int k=0;k<pp[n];k++)f[i][k]=(f[i][k]+1ll*f[j][k]*g[i-j][k])%mod; 37 ifmt(f[i]); 38 for(int j=0;j<pp[n];j++)f[i][j]=1ll*f[i][j]*inv[j]%mod; 39 for(int j=0;j<pp[n];j++)if(sz[j]!=i)f[i][j]=0; 40 if(i!=n)fmt(f[i]); 41 } 42 printf("%d ",f[n][pp[n]-1]); 43 return 0; 44 }
8.拉格朗日反演(zblzblzbl不会啦)
9.牛顿迭代(After WC)
10.多项式相关(After WC)

1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1000005,mod=998244353; 4 int fac[N],ifac[N],a[N],b[N],c[N],ans[N],t[N],r[N]; 5 int pw(int a,int b){int r=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)r=1ll*r*a%mod;return r;} 6 void ntt(int *a,int n,int f) 7 { 8 int l=1;while((1<<l)<n)l++; 9 for(int i=1;i<n;i++)r[i]=r[i>>1]>>1|((i&1)<<(l-1)); 10 for(int i=1;i<n;i++)if(i<r[i])swap(a[i],a[r[i]]); 11 for(int i=2;i<=n;i<<=1) 12 { 13 int wn=pw(3,(mod-1)/i); 14 if(f==-1)wn=pw(wn,mod-2); 15 for(int j=0;j<n;j+=i)for(int k=0,w=1;k<(i>>1);k++,w=1ll*w*wn%mod) 16 { 17 int u=a[j+k],v=1ll*w*a[j+k+(i>>1)]%mod; 18 a[j+k]=(u+v)%mod;a[j+k+(i>>1)]=(u-v+mod)%mod; 19 } 20 } 21 if(f==-1)for(int i=0,iv=pw(n,mod-2);i<n;i++)a[i]=1ll*a[i]*iv%mod; 22 } 23 void inv(int *a,int *b,int n) 24 { 25 if(n==1){b[0]=pw(a[0],mod-2);b[1]=0;return;} 26 inv(a,b,n>>1);int nn=n<<1; 27 for(int i=0;i<n;i++)t[i]=a[i]; 28 for(int i=n;i<nn;i++)t[i]=0; 29 ntt(t,nn,1);ntt(b,nn,1); 30 for(int i=0;i<nn;i++)b[i]=1ll*(2-1ll*t[i]*b[i]%mod+mod)*b[i]%mod; 31 ntt(b,nn,-1); 32 for(int i=n;i<nn;i++)b[i]=0; 33 } 34 int main() 35 { 36 int T;scanf("%d",&T); 37 int nn=1;while(nn<=200000)nn<<=1; 38 for(int i=fac[0]=1;i<=nn;i++)fac[i]=1ll*fac[i-1]*i%mod; 39 ifac[nn]=pw(fac[nn],mod-2); 40 for(int i=nn;i;i--)ifac[i-1]=1ll*ifac[i]*i%mod; 41 for(int i=0;i<nn;i++)a[i]=mod-ifac[i];a[0]=1; 42 inv(a,b,nn); 43 for(int i=0;i<nn;i++)c[i]=b[i]; 44 c[0]--;nn<<=1; 45 ntt(b,nn,1);ntt(c,nn,1); 46 for(int i=0;i<nn;i++)c[i]=1ll*c[i]*b[i]%mod; 47 ntt(b,nn,-1);ntt(c,nn,-1); 48 for(int i=0;i<nn;i++)ans[i]=1ll*c[i]*pw(b[i],mod-2)%mod; 49 while(T--){int x;scanf("%d",&x);printf("%d ",ans[x]);} 50 return 0; 51 }
11.生成函数(After WC)
Trick:五边形数计算划分数O(nsqrt(n))
12.原根
Trick:单位根反演 判断倍数关系
13.指标 BSGS 即求解 ax=b(mod c)
利用分块做到O(sqrt(n))或O(sqrt(n)log(n))
14.二次剩余 Cipolla 求解x2=a(mod b)
16.CRT
17.Lucas

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define mod 19491001 5 int fac[mod+5],ifac[mod+5]; 6 int pw(int a,int b){int r=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)r=1ll*r*a%mod;return r;} 7 void init() 8 { 9 for(int i=fac[0]=1;i<=mod;i++)fac[i]=1ll*fac[i-1]*i%mod; 10 ifac[mod-1]=pw(fac[mod-1],mod-2); 11 for(int i=mod-1;i;i--)ifac[i-1]=1ll*ifac[i]*i%mod; 12 } 13 int C(int a,int b){return a<0||b<0||a<b?0:1ll*fac[a]*ifac[b]%mod*ifac[a-b]%mod;} 14 int lucas(ll a,ll b){if(a<mod&&b<mod)return C(a,b);else return 1ll*lucas(a/mod,b/mod)*lucas(a%mod,b%mod)%mod;} 15 int main() 16 { 17 init();int T;scanf("%d",&T); 18 while(T--) 19 { 20 ll n,m;scanf("%lld%lld",&n,&m); 21 printf("%d ",lucas(n+m,n)); 22 } 23 return 0; 24 }
18.Miller-Rabin
19.Pollard-Rho
20.线性代数
21.杜教筛
22.min25筛
24.群论