各種反演等數學難題

CF997C Sky Full of Stars

n×nn\times n的網格內每個格子染三種顏色,其中至少有一行或一列是同一種顏色的方案數。

轉化爲求沒有一行或一列顏色相同。
直接枚舉相同的行列數進行容斥:
=3i=0n(ni)(1)ij=0n(nj)(1)j3(ni)(nj)+2i=1n(ni)(1)i3n(ni)(3i3)2×3n2=3i=0n(ni)(1)i(3ni1)n+2i=1n(ni)(1)i3n(ni)(3i3)2×3n2\begin{aligned}&=3\sum_{i=0}^n \binom ni(-1)^i \sum_{j=0}^n \binom nj(-1)^j 3^{(n-i)(n-j)} + 2\sum_{i=1}^n \binom ni(-1)^i 3^{n(n-i)}(3^i-3) - 2\times 3^{n^2} \\ &=3 \sum_{i=0}^n \binom ni (-1)^i (3^{n-i}-1)^n+ 2\sum_{i=1}^n \binom ni(-1)^i 3^{n(n-i)}(3^i-3) - 2 \times 3^{n^2}\end{aligned}
後面的那個式子是因爲iijj有一個爲00的時候相同的染色行列不一定只有三種方案。

AC Code\mathcal AC \ Code

#include<bits/stdc++.h>
#define mod 998244353
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define LL long long
using namespace std;

int n;
int Pow(int b,LL k){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1) r=1ll*r*b%mod;return r; }

int main(){
	scanf("%d",&n);
	int ans = 3ll * Pow(3,n*1ll*n) % mod , C = 1;
	rep(i,0,n){
		ans = (ans - 3ll * C * (i&1 ? -1ll : 1ll) * Pow(Pow(3,n-i)-1,n)) % mod;
		if(i) ans = (ans - 2ll * C * (i&1 ? -1ll : 1ll) * Pow(3,1ll*n*(n-i)) % mod * (Pow(3,i) - 3)) % mod;
		C = 1ll * C * (n-i) % mod * Pow(i+1,mod-2) % mod;
	}
	printf("%d\n",(ans+mod)%mod);
}

[AGC035F] Two Histograms

在這裏插入圖片描述
可以發現一個網格對應多個方案,當且僅當存在lx=y,ky=x1l_x = y , k_y = x-1,這時讓lx=y1,ky=xl_x=y-1,k_y=x也可以得到同樣的網格。
所以我們設lx=y,ky=x1l_x = y , k_y = x-1kyk_y不合法,容斥求出所有的合法方案即爲本質不同的網格方案(即我們只在所有可以有多個方案的網格只計算lx=y1,ky=xl_x=y-1,k_y=x這一種情況。)。
ans=i=0min(n,m)(ni)(1)i(mi)i!(m+1)ni(n+1)mians = \sum_{i=0}^{\min(n,m)} \binom ni (-1)^i\binom mi i! (m+1)^{n-i}(n+1)^{m-i}

AC Code\mathcal AC \ Code

#include<bits/stdc++.h>
#define mod 998244353
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define LL long long
using namespace std;

int n,m;
int Pow(int b,LL k){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1) r=1ll*r*b%mod;return r; }

int main(){
	scanf("%d%d",&n,&m);
	int Cn=1,Cm=1,ans=0,fc=1;
	rep(i,0,min(n,m)){
		ans = (ans + 1ll * Cn * Cm % mod * (i&1 ? -1ll : 1ll) * fc % mod * Pow(m+1,n-i) % mod * Pow(n+1,m-i)) % mod;
		Cn = 1ll * Cn * (n-i) % mod * Pow(i+1 , mod-2) % mod;
		Cm = 1ll * Cm * (m-i) % mod * Pow(i+1 , mod-2) % mod;	
		fc = 1ll * fc * (i+1) % mod;
	}
	printf("%d\n",(ans+mod)%mod);
}

LOJ #6181. 某個套路求和題

f(n)f(n)在質數處爲1-1,有平方因子數處爲00,其他時候爲11
所以答案等於i=1μ(i)ni22π(n)\sum_{i=1}\mu(i) \left\lfloor\frac {n}{i^2}\right\rfloor-2 \pi(n)
前者直接算,後者Min25Min_25
寫了一個很麻煩的實現:

#include<bits/stdc++.h>
#define maxn 200005
#define LL long long
#define mod 998244353
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--) 
using namespace std;

LL n,sn,a[maxn],s[maxn],mu[maxn];
double inv[maxn];
int cnt;
int ID(LL a){ return a <= sn ? a : cnt - n/a + 1; }

int main(){
	scanf("%lld",&n);
	sn = sqrt(n);
	for(LL i=1;i<=n;i++) a[++cnt] = (i = n / (n / i)) , s[cnt] = i - 1;
	for(LL i=2;i<=sn;i++){
		inv[i] = 1.0 / i;
		if(s[i] ^ s[i-1]) for(LL j=cnt,LIM=i*i;a[j]>=LIM;j--)
			s[j] -= s[ID((LL)(a[j] * inv[i] + 1e-9))] - s[i-1];	
	}
	for(int i=1;i<=cnt;i++) mu[i] = -s[i];
	for(LL i=sn;i>=2;i--) if(s[i] ^ s[i-1]) for(LL j=cnt,LIM=i*i;a[j]>=LIM;j--)
		mu[j] -= mu[ID((LL)(a[j] * inv[i] + 1e-9))] + s[i];
	for(int i=sn;i>=1;i--) mu[i] -= mu[i-1];
	mu[1] = 1;
	LL ans = - 2 * s[cnt];
	for(int i=1;i<=sn;i++) ans += mu[i] * (n / i / i);
	printf("%lld\n",(ans%mod+mod)%mod);
}

#528. 「LibreOJ β Round #4」求和

i=1nj=1mμ2(gcd(i,j))=d=1min(n,m)μ2(d)i=1ndj=1md[gcd(i,j)=1]=d=1min(n,m)μ2(d)p=1min(n,m)dμ(p)ndpmdp=D=1minn,mndmddDμ2(d)μ(Dd)\begin{aligned}&\sum_{i=1}^n \sum_{j=1}^m \mu^2(\gcd(i,j)) = \sum_{d=1}^{\min(n,m)} \mu^2(d)\sum_{i=1}^{\frac nd}\sum_{j=1}^{\frac md} [\gcd(i,j)=1]\\&=\sum_{d=1}^{\min(n,m)} \mu^2(d)\sum_{p=1}^{\frac {\min(n,m)}{d}} \mu(p)\lfloor \frac {n}{dp}\rfloor\lfloor \frac {m}{dp} \rfloor \\&=\sum_{D=1}^{\min n,m} \lfloor\frac nd\rfloor\lfloor\frac md\rfloor\sum_{d|D} \mu^2(d)\mu(\frac Dd)\end{aligned}

考慮dDμ2(d)μ(Dd)\sum_{d|D} \mu^2(d)\mu(\frac Dd),這是個積性函數,我們考慮質數的次方處的值,可以發現這個函數在p1,p3,p4...pc,c2p^1,p^3,p^4...p^c,c\neq 2處都爲00
而在p2p^2處爲μ(p)\mu(p),所以dDμ2(d)μ(Dd)=[x2=D]μ(x)\sum_{d|D} \mu^2(d)\mu(\frac Dd) = [x^2 = D]\mu(x)其中x=Dx = \lfloor\sqrt D \rfloor
所以預處理n\leq \sqrt nμ\mu的前綴和即可整除優化。

AC Code\mathcal AC \ Code

#include<bits/stdc++.h>
#define maxn 5000007
#define LL long long
#define mod 998244353
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--) 
using namespace std;

LL n,m;
int mu[maxn],pr[maxn],vis[maxn],cnt_pr;

int main(){
	scanf("%lld%lld",&n,&m);
	if(n > m) swap(n,m);
	mu[1]=1;
	int sn = sqrt(n);
	rep(i,2,sn){
		if(!vis[i]) pr[cnt_pr++] = i , mu[i] = -1;
		for(int j=0;pr[j] * i <= sn;j++){
			vis[i * pr[j]] = 1;
			if(i % pr[j] == 0){
				mu[i * pr[j]] = 0;
				break;
			}
			mu[i * pr[j]] = -mu[i];
		}
		mu[i] += mu[i-1];
	}
	int ans = 0;
	for(LL i=1,nxt;i<=n;i=nxt+1){
		nxt = min(n / (n / i) , m / (m / i));
		ans = (ans + 1ll * (n / i) % mod * (m / i % mod) % mod * (mu[(int)(sqrt(nxt)+1e-9)] - mu[(int)(sqrt(i-1)+1e-9)])) % mod;
	}
	printf("%d\n",(ans+mod)%mod);
}

LOJ #6244. 七選五

考慮一個固定的排列aa,大小爲rr,現在你要選出nnrr排列,求這個排列和aa中恰好有xx相等的方案數。

廣義容斥原理模板題:
廣義容斥原理:
β(x)\beta (x)爲欽定xx個條件滿足的方案數。
則恰好有xx個方案滿足的方案數f(x)=i=xn(1)ixβ(i)(ix)f(x) = \sum_{i=x}^n (-1)^{i-x}\beta(i)\binom {i}{x}
容斥係數爲(1)ix(ix)(-1)^{i-x}\binom ix是因爲在這裏插入圖片描述
所以對於這題答案=i=xr(ix)(1)i(ri)(niri)(ri)!=\sum_{i=x}^r\binom ix(-1)^i\binom ri \binom {n-i}{r-i}(r-i)!

AC Code\mathcal AC \ Code

#include<bits/stdc++.h>
#define maxn 1000007
#define LL long long
#define mod 1000000007
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--) 
using namespace std;

int n,k,x;
int fac[maxn],inv[maxn],invf[maxn];
int C(int n,int m){ return fac[n] * 1ll * invf[m] % mod * invf[n-m] % mod; }

int main(){
	fac[0] = fac[1] = inv[0] = inv[1]= invf[0] = invf[1] = 1;
	scanf("%d%d%d",&n,&k,&x);
	rep(i,2,n) fac[i] = 1ll * fac[i-1] *i  % mod, inv[i] = 1ll * (mod - mod /i) * inv[mod % i] % mod,
		invf[i] = 1ll * invf[i-1] * inv[i] % mod;
	int ans = 0;
	rep(i,x,k)
		ans = (ans + (i-x&1?-1ll:1ll)*C(i,x)%mod*C(k,i)%mod*fac[n-i]%mod*invf[n-k])%mod;
	printf("%d\n",(ans+mod)%mod);
}

[ARC101C] Ribbons on Tree

在這裏插入圖片描述
fi,jf_{i,j}表示以ii爲根的子樹內剩下jj個點未匹配的容斥係數和。
則每次可以強行讓ii到父親的邊不被塗色也就是強行匹配剩下的所有點,並乘上一個1-1的容斥係數。

AC Code\mathcal AC \ Code

#include<bits/stdc++.h>
#define maxn 5005
#define LL long long
#define iv2 500000004
#define mod 1000000007
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--) 
using namespace std;

int n,f[maxn][maxn],sz[maxn],fac[maxn],pw[maxn],invf[maxn],inv[maxn];
vector<int>G[maxn];
int C2(int x){ return 1ll * x * (x-1) / 2 % mod; }

void dfs(int u,int ff){
	int v;f[u][1] = sz[u] = 1;
	rep(i,0,G[u].size()-1) if((v=G[u][i])^ff){
		dfs(v,u);
		static int g[maxn]={};
		rep(j,0,sz[u]+sz[v]) g[j] = 0;
		rep(j,0,sz[u]) rep(k,0,sz[v]) g[j+k] = (g[j+k] + 1ll * f[u][j] * f[v][k]) % mod;
		rep(j,0,sz[u]+sz[v]) f[u][j] = g[j];
		sz[u] += sz[v];
	}
	rep(j,1,sz[u]) if(j%2==0)
		f[u][0] = (f[u][0] + f[u][j] * 1ll * fac[j] % mod * pw[j/2] % mod * invf[j/2]) % mod;
	if(ff) f[u][0] = -f[u][0];
}

int main(){
	scanf("%d",&n);
	rep(i,1,n-1){
		int u,v;scanf("%d%d",&u,&v);
		G[u].push_back(v),G[v].push_back(u);
	}
	fac[0] = fac[1] = pw[0] = 1 , pw[1] = iv2;
	inv[0] = inv[1] = invf[0] = invf[1] = 1;
	rep(i,2,n) fac[i] = 1ll * fac[i-1] * i % mod , pw[i] = 1ll * iv2 * pw[i-1] % mod,inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod,
		invf[i] = 1ll * invf[i-1] * inv[i] % mod;
	dfs(1,0);
	printf("%d\n",f[1][0]);
}

LOJ 「美團 CodeM 初賽 Round A」二分圖染色

以訛傳訛真離譜
將問題轉化爲棋盤模型,則是同顏色的棋子不能在同一行或同一列,不同顏色的棋子不能在同一個格子裏。
fnf_n爲在n×nn \times n的棋盤內放置一種顏色的棋子的方案數。
則不同顏色的棋子不能在同一個格子裏這個條件可以得到容斥一下ans=i=0(1)i(ni)2i!fni2ans = \sum_{i=0} (-1)^i \binom ni^2i!f_{n-i}^2
對於fnf_n有遞推式fn=2nfn1(n1)2fn2f_n = 2nf_{n-1}-(n-1)^2f_{n-2}
這部分的證明我看到的網上的題解都是錯的。
我們可以在1...n11...n-1選擇一列xx,然後在nnxx列(下面簡稱(n,x)(n,x))放置一個棋子,同時將之前fn1f_{n-1}中對於n1n-1n1n-1列的方案作出x...n1x...n-1列平移到x+1...nx+1...n列的操作,這樣我們就得到了一個合法方案,同樣我們也可以在1...n11...n-1選擇一行xx然後在(x,n)(x,n)等做類似的操作,也可以直接在(n,n)(n,n)放置一個棋子,同時也可以不放,一共2n2n種操作。
但是發現選擇一列和選擇一行這兩種操作構造出來的棋盤可能會重,如果重了一定是因爲nn行上有一個棋子nn列上也有一個棋子,並且這兩個棋子都不在(n,n)(n,n),所以我們就求出nn行上有一個棋子,nn列上有一個棋子的方案數也即(n1)2fn2(n-1)^2f_{n-2},然後減去即可。

AC Code\mathcal AC \ Code

#include<bits/stdc++.h>
#define mod 1000000007
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define maxn 10000007
using namespace std;

int n,inv[maxn],f[maxn];

int main(){
	scanf("%d",&n);
	inv[0] = inv[1] = f[0] = 1 , f[1] = 2;
	rep(i,2,n) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod , 
		f[i] = (2ll * i * f[i-1] - (i-1ll) * (i-1ll) % mod * f[i-2]) % mod;
	int ans = 0 , C = 1;
	rep(i,0,n)
		ans = (ans + (i&1?-1ll:1ll) * C * f[n-i] % mod * f[n-i]) % mod,
		C = 1ll * C * (n-i) % mod * (n-i) % mod * inv[i+1] % mod;
	printf("%d\n",(ans+mod)%mod);
}

LOJ #572. 「LibreOJ Round #11」Misaka Network 與求和

i=1Nj=1Nf(gcd(i,j))kmod232\sum_{i=1}^{N} \sum_{j=1}^{N} f(\operatorname{gcd}(i, j))^{k} \bmod 2^{32}
g(x)=f(x)kg(x) = f(x)^k
i=1nj=1ng(gcd(i,j))=d=1ng(d)i=1ndj=1nd[(i,j)=1]\begin{aligned}&\sum_{i=1}^n\sum_{j=1}^n g(\gcd(i,j))=\sum_{d=1}^n g(d)\sum_{i=1}^\frac nd \sum_{j=1}^{\frac nd} [(i,j)=1]\end{aligned}
因爲gg的定義是次大質因子的KK次方,次大質因子一定是min25min_25中我們篩到的質因子(不像什麼次小質因子min25min_25篩過程中篩不到需要預處理噁心人,比如51nod 1847 奇怪的數學題),所以可以直接篩,後面就是一個ϕ\phi的前綴和,具體來說他等於2i=1ndϕ(i)nd2\sum_{i=1}^{\frac nd} \phi(i) - \lfloor\frac nd\rfloor

用遞推版的Min25Min_25成功水到rk1rk1
AC Code\mathcal AC \ Code

#include<bits/stdc++.h>
#define maxn 100005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;

int n,K,sn,cnt,s[maxn],s1[maxn],a[maxn],g[maxn],phi[maxn];
int ID(int a){ return a <= sn ? a : cnt - n/a + 1; }
int Pow(int b,int k){ int r=1;for(;k;k>>=1,b=b*b)if(k&1)r=r*b;return r; }
double inv[maxn];

int main(){
	scanf("%d%d",&n,&K);
	sn = sqrt(n);
	for(int i=1;i<=n;i++) a[++cnt] = (i = (n / (n / i))) , 
		s[cnt] = i - 1 , s1[cnt] = 1ll * i * (i+1) / 2 - 1;
	for(int i=2;i<=sn;i++){
		inv[i] = 1.0 / i;
		if(s[i] ^ s[i-1]) for(int j=cnt,LIM=i*i;a[j]>=LIM;j--){
			int t = ID((int)(a[j] * inv[i] + 1e-9));
			s[j] -= s[t] - s[i-1],
			s1[j] -= (s1[t] - s1[i-1]) * i;
		}
	}
	for(int i=1;i<=cnt;i++) phi[i] = s1[i] - s[i];
	for(int i=sn;i>=1;i--) if(s[i] ^ s[i-1]){
		int pw = Pow(i,K);
		for(int j=cnt,LIM=i*i;a[j]>=LIM;j--){
			double iv = inv[i];
			for(int k=i,f=i-1;1ll*k*i <= a[j];k*=i,f*=i,iv/=i){
				int t = ID((int)(a[j] * iv + 1e-9));
				g[j] += pw * (s[t] - s[i-1]) + g[t];
				phi[j] += f * (phi[t] - s1[i] + s[i] + i);
			}
		}
	}
	for(int i=1;i<=cnt;i++) phi[i] ++ , g[i] += s[i];
	int ans = 0;
	for(int i=1,nxt;i<=n;i=nxt+1){
		nxt = n/(n/i);
		ans += (g[ID(nxt)] - g[ID(i-1)]) * (2 * (phi[ID(n/i)] - 1) + 1);
	}
	unsigned int ret = ans;
	printf("%u\n",ret);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章