【2018沈阳现场赛I】Distance Between Sweethearts
题意
分析
看似是期望问题,但是没有权重,就是求平均值,而答案要求乘上方案总数,所以 这是一个计数问题
考虑max,若三个绝对值分别为(x,y,z),则max = max(x,y,z)
distance = max ^ Ib ^ (Ib+x) ^ Ab ^ (Ab + y) ^ Gb ^ (Gb + z)
我们统计出每种Ib^Ig ( |Ib - Ig| ≤ x ) 的方案数,同理其他属性也是,总共产生三个数组
根据乘法原理,我们可以求得 k = Ib ^ (Ib+x) ^ Ab ^ (Ab + y) ^ Gb ^ (Gb + z) 的方案数为∑ (cnt_I[ Ib ^ (Ib+x) ] * cnt_A[Ab ^ (Ab + y)] * cnt_G[Gb ^ (Gb + z)]),这里就可以做异或卷积
但我们还要统计max,那在max值固定的情况下,也就是x,y,z至少有一个等于一个定值max,这样的方案数如何统计呢?
考虑容斥,令 某一种方案为Ib ,Ig = (Ib+x), Ab , Ag =(Ab + y) , Gb ,Gg = (Gb + z) 记作 (x,y,z)
如果我们计算出来了x<=max && y<=max && z <=max的方案数A,又计算出了x<max && y<max && z <max 的方案数B , 上述的方案数就等于A - B,
所以可以每次枚举max值的时候,去累加cnt,这样单种元素的绝对值都不超过max
btw:为什么我自己以前fwt板子挂了啊 TAT ,借鉴了聚聚的板子
代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; ll IB,AB,GB,IG,AG,GG; ll cnt[3][2048]; ll a[3][2048]; ll pre[2048]; ull ans; void csh(){ memset(cnt,0,sizeof(cnt)); memset(pre,0,sizeof(pre)); } void fwt(ll a[],int n,int v) { for(int d=1;d<n;d<<=1) { for(int m = d<<1,i=0;i<n;i+=m) { for(int j=0;j<d;j++){ ll x = a[i+j],y = a[i+j+d]; if(v == 1) a[i+j] = (x+y),a[i+j+d] = (x-y); else a[i+j] = (x+y)/2,a[i+j+d] = (x-y)/2; } } } } int main() { ios::sync_with_stdio(false); int _,ca=0;cin>>_; while(_--) { cin>>IB>>AB>>GB>>IG>>AG>>GG; csh(); ans=0; for(int maxx = 0;maxx <=2000;maxx++) { // cout<<"MAX = "<<maxx<<endl; for(int i=0;i<=IB&&i+maxx<=IG;i++) cnt[0][i^(i+maxx)]++; if(maxx>0) for(int i=0;i<=IG&&i+maxx<=IB;i++)cnt[0][i^(i+maxx)]++; for(int i=0;i<=AB&&i+maxx<=AG;i++) cnt[1][i^(i+maxx)]++; if(maxx>0) for(int i=0;i<=AG&&i+maxx<=AB;i++)cnt[1][i^(i+maxx)]++; for(int i=0;i<=GB&&i+maxx<=GG;i++) cnt[2][i^(i+maxx)]++; if(maxx>0) for(int i=0;i<=GG&&i+maxx<=GB;i++)cnt[2][i^(i+maxx)]++; for(int i=0;i<2048;i++) a[0][i] = cnt[0][i],a[1][i] = cnt[1][i],a[2][i]=cnt[2][i]; fwt(a[0],2048,1); fwt(a[1],2048,1); fwt(a[2],2048,1); for(int i=0;i<2048;i++) { a[0][i] = a[0][i] * a[1][i] * a[2][i]; } fwt(a[0],2048,-1); for(int i=0;i<2048;i++) { ans+=(a[0][i] - pre[i])*(i^maxx); pre[i] = a[0][i]; } } cout<<"Case #"<<++ca<<": "<<ans<<endl; } }