bzoj3198[Sdoi2013]spring 容斥+hash
3198: [Sdoi2013]spring
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1143 Solved: 366
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
3 3
1 2 3 4 5 6
1 2 3 0 0 0
0 0 0 4 5 6
Sample Output
2
HINT
Dragonite修正数据
Source
容斥简单,但是hash有点麻烦。
ans= 至少k的对数*C(k,k) - 至少k+1的对数*C(k+1,k) + 至少k+2的对数*C(k+2,k) ...
对于这个C(i+k,k),我的理解这对数被计算了C(k+i,k)次
hash判断冲突。。至少我不会,别人博客学习了一波
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #define ll long long #define N 100005 #define mod 2150527 using namespace std; int a[N][10],bin[10],hd[mod+10],vis[mod+10],c[10][10],sum[N],nxt[N],n,m; ll val[N]; void pre(){ for(int i=0;i<=6;i++)c[i][0]=c[i][i]=1; for(int i=1;i<=6;i++) for(int j=1;j<i;j++) c[i][j]=c[i-1][j-1]+c[i-1][j]; } ll calc(int st){ ll ans=0;int tot=0; for(int i=1;i<=n;i++){ ll tmp=0;int j,k; for(j=1;j<=6;j++)if(st&bin[j-1])tmp=tmp*1000003+a[i][j]; j=tmp%mod;j<0?j+=mod:1; if(vis[j]!=st){vis[j]=st;hd[j]=0;} for(k=hd[j];k;k=nxt[k]){ if(val[k]==tmp){ ans+=sum[k];sum[k]++; break; } } if(!k){ val[++tot]=tmp; sum[tot]=1;nxt[tot]=hd[j];hd[j]=tot; } } return ans; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=6;j++) scanf("%d",&a[i][j]); bin[0]=1;pre(); for(int i=1;i<=8;i++)bin[i]=bin[i-1]<<1; ll ans=0; for(int i=0;i<64;i++){ int cnt=0; for(int j=0;j<6;j++) if(i&bin[j])cnt++; if(cnt<m)continue; ll t=calc(i)*c[cnt][m]; if((cnt-m)%2)ans-=t; else ans+=t; } cout<<ans; return 0; }
If you live in the echo,
your heart never beats as loud.
如果你生活在回声里,
你的心跳声永远不会轰鸣作响。