CF643F Bears and Juice
题解
感觉很有意思啊。
我们首先要考虑的事情就是,我们的策略应当对于每一种情况都适用,所以说我们不能安排超过 \(p\) 头熊去喝同一个酒桶中的饮料,同样的,我们也不能使得两个酒桶的饮酒方案相同,不然如果出现了对应此方案的醉倒情况,你无法判断到底是哪一个。
相当于题目就是在问我们有多少种醉倒情况不同的饮酒方案。
我们考虑首先醉倒的人数可以不同,同时醉倒的天数可以不同,醉倒的熊也可以不同。
所以我们对于饮酒天数为 \(q\) 的情况,我们可以列出下面的式子(在这里熊是可以区分的)。
\[R_q=\sum_{i=0}^{\min(n-1,p)}C_n^i\cdot q^i
\]
然后结合题目的式子,我们最后要求的就是:
\[f(q)=\bigoplus _{i=1}^qi\times(\sum_{j=0}^{\min(n-1,p)}C_n^j\cdot i^j)\bmod 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\n",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\n",res);
return 0;
}