ABC-typewriter-(组合数+容斥)

F

题意:
就是给你n个键盘,每个键盘可以打一些字母,然后让你用键盘打出长度为m的字母的方案数有多少种。

思考:
刚开始我以为是每次只能用一个键盘,实际上可以随便用。但是很明显有k个字母的方案数就是k的m次方,但是怎么去重呢。其实根据去重原理,最简单的是3个键盘,1+2+3-12-13-23+123。然后递推一下就是对于一个多重集合去重的就是二进制枚举用了几个键盘,对于奇数加还是偶数加,就看看你到底是干什么,这个题首先是没有方案,拿过来键盘后才有方案,所以1个键盘的时候加,2个键盘的时候减…。所以如果是奇数个就加上方案数,如果是偶数个就减去方案数。 对了对于求方案的时候,是这些键盘共有的字母的方案数,因为如果不共有,比如两个键盘都有字母a,我现在又拿一个键盘,但是没有字母a,这时候对字母a就不要再去重了,因为他没有字母a。
之前就做过这种容斥类型的:无关。一定要对n可以2进制枚举范围的有敏感。

代码:

int T,n,m,k;
int va[N];

int ksm(int a,int b)
{
	int sum = 1;
	while(b)
	{
		if(b&1) sum = sum*a%mod;
		a = a*a%mod;
		b >>= 1;
	}
	return sum;
}

signed main()
{
	IOS;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		string s;
		cin>>s;
		for(auto t:s) va[i] |= 1ll<<(t-'a');
	}
	int ans = 0;
	for(int i=1;i<(1ll<<n);i++)
	{
		int now = (1ll<<26)-1,cnt = 0,res = 0;
		for(int j=0;j<n;j++)
		{
			if(i>>j&1)
			{
				cnt++;
				now &= va[j+1];
			}
		}
		for(int j=0;j<26;j++) if(now>>j&1) res++;
		if(cnt%2) ans = (ans+ksm(res,m))%mod;
		else ans = (ans-ksm(res,m))%mod;
	}
	ans = (ans%mod+mod)%mod;
	cout<<ans;
	return 0;
}

总结:
多多思考积累经验。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值