【原题】
【题解】这道题明明是水题,坑了我两天!!!真是伤心。发现哈希都不熟练了。
首先很容易想到是2^6枚举01状态,使得1的个数不小于K。比如枚举了0110000,我们就可以用一个哈希来处理个数。然后统计一下结果即可。开始的代码如下:
【代码1】
#include<cstdio> #include<cstring> #include<algorithm> #define N 100005 using namespace std; int n,k,num,i,j,p,x[N][6],status,Time,flag; typedef long long ll;ll ans,h1,h2; const ll hash1=999997; const ll hash2=233333; int f1[hash1],f2[hash2]; int main() { scanf("%d%d",&n,&k);num=1<<6; for (i=1;i<=n;i++) for (j=0;j<6;j++) scanf("%d",&x[i][j]); for (status=0;status<num;status++) { flag=0; for (j=0;j<6;j++) flag+=(status&(1<<j))?1:0; if (flag<k) continue; memset(f1,0,sizeof(f1)); memset(f2,0,sizeof(f2)); for (i=1;i<=n;i++) { h1=1;h2=1; for (j=0;j<6;j++) if (status&(1<<j)) { h1=(h1+ll(1<<j)*ll(x[i][j]))%hash1; h2=(h2+ll(1<<j)*ll(x[i][j]))%hash2; } Time=min(f1[h1],f2[h2]); ans+=(long long)Time; f1[h1]++;f2[h2]++; } } printf("%lld",ans); return 0; }
【代码2】
#include<cstdio> #include<cstring> #include<algorithm> #define N 100005 using namespace std; int n,k,num,i,j,p,x[N][6],C[7][7],status,Time,flag,del; typedef long long ll;ll ans,h1,h2; const ll hash1=999997;const ll base1=97; const ll hash2=233333;const ll base2=23; int f1[hash1],f2[hash2]; int main() { scanf("%d%d",&n,&k); for (i=1;i<=n;i++) for (j=0;j<6;j++) scanf("%d",&x[i][j]); C[0][0]=1; for (i=1;i<=6;i++) { C[i][0]=1; for (j=1;j<=i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1]; } for (status=0;status<64;status++) { flag=0; for (j=0;j<6;j++) flag+=(status&(1<<j))?1:0; if (flag<k) continue; memset(f1,0,sizeof(f1)); memset(f2,0,sizeof(f2)); Time=0; for (i=1;i<=n;i++) { h1=0ll;h2=0ll; for (j=0;j<6;j++) if (status&(1<<j)) { h1=(h1*base1+ll(x[i][j]))%hash1; h2=(h2*base2+ll(x[i][j]))%hash2; } Time+=min(f1[h1],f2[h2]); f1[h1]++;f2[h2]++; } del=((flag-k)&1)?-1:1; ans+=(long long)Time*del*C[flag][k]; } printf("%lld",ans); return 0; }
【AC代码】
#include<cstdio> #include<cstring> #include<algorithm> #define N 100005 using namespace std; int n,k,num,i,j,p,x[N][6],C[7][7],status,flag,pre,cnt,t; typedef long long ll;ll ans,h,Time,del; const ll hash=99997;const ll base=97; struct arr{int num,s,next;}a[100005]; int end[hash],temp[7],f[100005][7],data[100005]; ll doit(int k) { int j; for (int i=end[k];i;i=a[i].next) { j=0; if (a[i].num==t) for (j=1;j<=t;j++) if (temp[j]!=f[i][j]) break; if (j==t+1) return ++a[i].s; } if (!end[k]) data[++pre]=k; cnt++;a[cnt].num=t;a[cnt].s=0;a[cnt].next=end[k];end[k]=cnt; for (j=1;j<=t;j++) f[cnt][j]=temp[j];return 0; } inline int Read() { int x=0;char ch=getchar();bool positive=1; for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') positive=0; for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; return positive?x:-x; } int main() { scanf("%d%d",&n,&k); for (i=1;i<=n;i++) for (j=0;j<6;j++) x[i][j]=Read(); C[0][0]=1; for (i=1;i<=6;i++) { C[i][0]=1; for (j=1;j<=i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1]; } for (status=0;status<64;status++) { flag=0;pre=0; for (j=0;j<6;j++) flag+=(status&(1<<j))?1:0; if (flag<k) continue; Time=0ll; for (i=1;i<=n;i++) { h=0ll;t=0; for (j=0;j<6;j++) if (status&(1<<j)) h=(h*base+ll(x[i][j]))%hash,temp[++t]=x[i][j]; Time+=doit(h); } cnt=0;for (i=1;i<=pre;i++) end[data[i]]=0; del=((flag-k)&1)?-1ll:1ll; ans+=(ll)(Time*del*C[flag][k]); } printf("%lld",ans); return 0; }