CF643F Bears and Juice

题解

感觉很有意思啊。

我们首先要考虑的事情就是,我们的策略应当对于每一种情况都适用,所以说我们不能安排超过 (p) 头熊去喝同一个酒桶中的饮料,同样的,我们也不能使得两个酒桶的饮酒方案相同,不然如果出现了对应此方案的醉倒情况,你无法判断到底是哪一个。

相当于题目就是在问我们有多少种醉倒情况不同的饮酒方案。

我们考虑首先醉倒的人数可以不同,同时醉倒的天数可以不同,醉倒的熊也可以不同。

所以我们对于饮酒天数为 (q) 的情况,我们可以列出下面的式子(在这里熊是可以区分的)。

[R_q=sum_{i=0}^{min(n-1,p)}C_n^icdot q^i ]

然后结合题目的式子,我们最后要求的就是:

[f(q)=igoplus _{i=1}^qi imes(sum_{j=0}^{min(n-1,p)}C_n^jcdot i^j)mod 2^{32} ]

发现暴力就可以了。

代码如下

#include<bits/stdc++.h>
using namespace std;
#define uint unsigned int
#define It map<int,int>::iterator
const int Q=2e6+5,P=135;
int n,p,q,cnt[P];
uint zuhe[P],res=0;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
uint ksm(uint x,int k){
	uint res=1;
	for(;k;k>>=1,x=x*x)
	if(k&1) res=res*x;
	return res;
}
uint cal(int n,int m){
	uint res=1;
	for(int i=1;i<=m;++i) cnt[i]=1;
	for(int i=n;i>=n-m+1;--i){
		int now=i;
		for(int j=m;j>=1;--j){
			int tmp=gcd(now,j);
			while(tmp>1&&cnt[j]){
				now/=tmp,cnt[j]--;
				cnt[j/tmp]++;
				tmp=gcd(now,j);
			}
		}
		res*=(uint)now;
	}
	// printf("%d
",cnt[1]);
	return res;
}
int main(){
	cin>>n>>p>>q;
	for(int i=0;i<=min(p,n-1);++i) zuhe[i]=cal(n,i);
	for(int i=1;i<=q;++i){
		uint sum=0;
		for(int j=0;j<=min(p,n-1);++j)
		sum+=zuhe[j]*ksm(i,j);
		sum*=(uint)i,res^=sum;
	}
	printf("%u
",res);
	return 0;
}
原文地址:https://www.cnblogs.com/Point-King/p/14243358.html