BZOJ 3198: [Sdoi2013]spring [容斥原理 哈希表]
2017-03-25 12:45
369 查看
3198: [Sdoi2013]spring
题意:n个物品6个属性,求有多少不同的年份i,j满足有k个属性对应相等一开始读错题了,注意是对应相等 第i个属性只能和第i个属性对应
容斥一下
\[
恰好k个相等=\ge k个相等 \ -\ \ge k+1个相等\ +\ \ge k+2个相等 \ ...
\]
\(2^6\)枚举哪些属性对应相等,哈希一下计算这些属性相等的个数,这时候其他是任意的因为是\(\ge\)
这样还不行,容斥系数还要乘上\(\binom{i}{k}\),因为两个k+1个属性对应相等的物品贡献了\(\binom{k+1}{k}\)个k个属性相等
其实就是说,比如\(\ge k\)的时候我们求到的\(\ge k\)个相等的方案数,并不是这样的物品对个数,对于一个\(k+i\)个属性对应相等的物品对我们其实考虑了\(\binom{k+i}{k}\)次,这里本身就出现了重复(不是容斥的原因是我们统计个数的原因),所以要额外消去这个的影响,方法就是乘上那个组合数
我在这里进行了证明
属性值太大很容易冲突所以要用哈希表
然后去学了哈希表...貌似P越小越快啊
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=1e5+5, M=23333, P=1001001;//1234567; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n, k, a [7], c[7][7]; struct HashList{ struct meow{int id, c, ne;} e[N*64]; int cnt, h[P], tim[P], Cl; inline void ini(){Cl++;} inline bool same(int x, int y, int s) { for(int i=1; i<=6; i++) if(s&(1<<(i-1)) && a[x][i] != a[y][i]) return false; return true; } int hash(int *a, int s) { ll val=0; for(int j=1; j<=6; j++) if(s&(1<<(j-1))) val = (val*M%P + a[j]%P)%P; return val; } int insert(int id, int s) { int val=hash(a[id], s); //printf("ins %d %d %d\n",id,s,val); if(tim[val] != Cl) h[val]=0, tim[val]=Cl; for(int i=h[val];i;i=e[i].ne) if(same(e[i].id, id, s)) {e[i].c++; return e[i].c-1;} e[++cnt]=(meow){id, 1, h[val]}; h[val]=cnt; return 0; } }H; ll cal(int s) { H.ini(); ll ans=0; for(int i=1; i<=n; i++) ans += H.insert(i, s); return ans; } inline int one(int x) { int ans=0; while(x) ans++, x&=x-1; return ans; } ll cnt[7]; int main() { //freopen("in","r",stdin); n=read(); k=read(); for(int i=1; i<=n; i++) for(int j=1; j<=6; j++) a[i][j]=read(); c[0][0]=1; for(int i=1; i<=6; i++) { c[i][0]=1; for(int j=1; j<=i; j++) c[i][j] = c[i-1][j] + c[i-1][j-1]; } int All=1<<6; for(int s=0; s<All; s++) cnt[one(s)] += cal(s); ll ans=0; for(int i=k; i<=6; i++) ans += (( (i-k)&1 ) ? -1 : 1) * c[i][k] * cnt[i]; printf("%lld\n",ans); }
相关文章推荐
- bzoj 3198 [Sdoi2013]spring(容斥原理+Hash)
- [BZOJ3198][Sdoi2013]spring(容斥原理+Hash)
- bzoj3198【SDOI2013】spring
- bzoj 3198: [Sdoi2013]spring 题解
- [BZOJ3198][SDOI2013]Spring(容斥+Hash)
- BZOJ 3198([Sdoi2013]spring-Hash判重+容斥原理)
- [BZOJ 3198] [Sdoi2013] spring 【容斥 + Hash】
- 【SDOI2013】【BZOJ3198】spring
- [BZOJ3198][Sdoi2013]spring(hash+容斥原理+组合数学)
- bzoj3198 [Sdoi2013]spring 哈希表+容斥
- bzoj3198 [sdoi2013] spring 哈希挂表+容斥
- bzoj3198[Sdoi2013]spring 容斥+hash
- bzoj 3198: [Sdoi2013]spring (hash+容斥原理)
- BZOJ 3198 SDOI2013 spring
- BZOJ 3198 Sdoi2013 spring Hash+容斥原理
- [BZOJ3129][Sdoi2013]方程(容斥原理+扩展lucas)
- bzoj3198 spring hash&容斥原理
- BZOJ_3129_[Sdoi2013]方程_组合数学+容斥原理
- bzoj 3198: [Sdoi2013]spring hash+容斥原理
- 3198: [Sdoi2013]spring【容斥原理+hash】