HDU 6397(2018多校第8场1001) Character Encoding 容斥

Posted pkgunboat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6397(2018多校第8场1001) Character Encoding 容斥相关的知识,希望对你有一定的参考价值。

听了杜教的直播后知道了怎么做,有两种方法,一种构造函数(现在太菜了,听不懂,以后再补),一种容斥原理。

知识补充1:若x1,x2,.....xn均大于等于0,则x1+x2+...+xn=k的方案数是C(k+m-1,m-1)种(貌似紫书上有,记不太清了)。

知识补充2:若限制条件为n(即x1,x2....xn均小于n,假设有c个违反,则把k减掉c个n(相当于把c个超过n的数也变成大于等于0的),就可以套用知识1的公式了。

则最后的答案为sum( (-1)^c * C(m , c) * C(m-1+k-n*c , m-1) );

这个题貌似要预处理出乘法逆元,不然会TLE。我的lucas定理做法超时了。。。

借鉴了杜教链接中的代码,O(n)时间预处理:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL mod=998244353;
const int maxn=203000;
LL f[maxn],fv[maxn];//f是阶乘,fv是乘法逆元 
LL quick_power(LL a,LL b){
	LL ans=1;
	for(;b;b>>=1){
		if(b&1)ans=ans*a%mod;
		a=a*a%mod;
	}
	return ans;
}
void init(){//初始化 
	f[0]=1;
	for(LL i=1;i<maxn;i++)
		f[i]=(f[i-1]*i)%mod;
	fv[maxn-1]=quick_power(f[maxn-1],mod-2);
	for(LL i=maxn-1;i>0;i--){
		fv[i-1]=fv[i]*i%mod;
	}
}
LL C(LL n,LL m){//这样可以O(1)计算出组合数 
	if(n<0||m<0||n<m)return 0;
	return f[n]*(fv[m])%mod*fv[n-m]%mod;
}
int main(){
	LL n,m,k,ans;
	int T;
	init();
	scanf("%d",&T);
	while(T--){
		scanf("%lld%lld%lld",&n,&m,&k);
		LL ans=0;
		for(int c=0;c*n<=k;c++){//容斥 
			if(c&1)ans=(ans-C(m,c)*C(k-c*n-1+m,m-1)%mod+mod)%mod;
			else ans=(ans+C(m,c)*C(k-c*n-1+m,m-1)%mod)%mod;
		}
		printf("%lld
",ans);
	}
} 

  还是附上超时代码,单次查询是O(lgn)的,如果查询次数比较少可以用这个,可以当作模板。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL mod=998244353;
LL power(LL a){
	if(a&1)return -1;
	return 1;
}
LL quick_power(LL a,LL b){
	LL ans=1%mod;
	while(b){
		if(b&1){
			ans=ans*a%mod;
			b--;
		}
		b>>=1;
		a=a*a%mod; 
	}
	return ans;
} 
LL C(LL n,LL m){
	if(m>n)return 0;
	LL ans=1;
	for(int i=1;i<=m;i++){
		LL a=(n+i-m)%mod;
		LL b=i%mod;
		ans=ans*(a*quick_power(b,mod-2)%mod)%mod;
	}
	return ans;
}
LL lucas(LL n,LL m){
	if(m==0)return 1;
	return C(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
}
int main(){
	LL n,m,k,ans;
	int T;
	scanf("%d",&T);
	while(T--){
		ans=0;
		scanf("%lld%lld%lld",&n,&m,&k);
		for(LL i=0;i*n<=k;i++){
			ans=(ans+(((power(i)*lucas(m,i))%mod)*lucas(m-1+k-n*i,m-1))%mod)%mod;
		}
		printf("%lld
",ans);
	}
}  

  

 

以上是关于HDU 6397(2018多校第8场1001) Character Encoding 容斥的主要内容,如果未能解决你的问题,请参考以下文章

2018多校第6场 1013 hdu6373 Pinball

杭电2018多校第一场(2018 Multi-University Training Contest 1) 1001.Maximum Multiple (HDU6298)-数学思维题(脑子是个好东西,

2017多校第8场 HDU 6143 Killer Names 容斥,组合计数

hdu6406 Taotao Picks Apples 多校第8场1010

HDU 6395(2018多校第7场1010)Sequence

2017多校第8场 HDU 6133 Army Formations 线段树合并