【题解】礼物 | [洛谷 P4916] 魔力环【20210113 省选模拟赛】【Burnside引理 容斥 组合数】

题目链接

题目链接(加强,略有不同)

题意

问有多少种本质不同的项链,满足:

  • (n) 个黑色珠子,(m) 个白色珠子;
  • 连续的白色珠子不超过 (k) 个。

旋转同构算作相同,翻转同构算作不同。

(n,mleq 10^6)(Tleq 5) 组询问。

题解

Burnside 引理,于是不考虑本质不同的限制。

先假设项链从黑色珠子开始,最后乘上 (dfrac{n'+m'}{n'}) 即可。考虑项链是由许多 黑+白*i 的段拼成的,故答案为:

[[x^{m+n}] (x+x^2+cdots +x^{k+1})^n=[x^m] (x^0+x^1+cdots +x^k)^n ]

考虑其组合意义:用 (n) 个不大于 (k) 的数凑出 (m),于是容斥枚举多少个数大于 (k)

[sum_{i=0}^n (-1)^idbinom{n}{i}dbinom{m-1-i(k+1)}{n-1} ]

#include<bits/stdc++.h>
using namespace std;
const int N=4e6,mod=998244353,G=3;
int qpow(int x,int y){
	int ans=1;
	while(y){
		if(y&1)ans=ans*1ll*x%mod;
		x=x*1ll*x%mod;
		y>>=1;
	}
	return ans;
}
int fac[N],ifac[N];
int binom(int n,int m){
	if(m<0||m>n)return 0;
	return fac[n]*1ll*ifac[m]%mod*ifac[n-m]%mod;
}

int t=0;
int calc(int n,int m,int k){
	int ans=0;
	m=n-m;
	for(int i=0;i*(k+1)<n&&i<=m;i++)
		ans=(ans+(i&1?mod-1ll:1ll)*binom(m,i)%mod*binom(n-1-i*(k+1),m-1))%mod;
	ans=ans*1ll*t%mod;
	return ans;
}

int gcd(int x,int y){
	return x?gcd(y%x,x):y;
}
int q[N];

int main(){
	int T;cin>>T;
	while(T--){
		int n,m,k;
		cin>>n>>m>>k;
		t=qpow(n-m,mod-2)*1ll*n%mod;
		if(n==m){
			printf("%d
",k==n);
			continue;
		}
		fac[0]=1;for(int i=1;i<=n+m;i++)fac[i]=fac[i-1]*1ll*i%mod;
		ifac[n+m]=qpow(fac[n+m],mod-2);
		for(int i=n+m-1;i>=0;i--)ifac[i]=ifac[i+1]*(i+1ll)%mod;
		int sum=0,g=gcd(n,m);
		for(int i=1;i<=n;i++)q[i]=0;
		for(int i=1;i<=n;i++){
			int t=n/gcd(n,i);
			if(m%t)continue;
			if(n%i==0)
				sum=(sum+(q[t]=calc(n/t,m/t,k)))%mod;
			else
				sum=(sum+q[t])%mod;
		}
		printf("%d
",sum*1ll*qpow(n,mod-2)%mod);
	}
}

原文地址:https://www.cnblogs.com/wallbreaker5th/p/14280611.html