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修正数据
题解
前置知识:广义容斥原理
由于是要求恰好k个满足的方案数,考虑容斥。
设$\\alpha (x) $表示至少满足有x个相等的方案数,答案即为:
\\[\\sum _{i=k}^n(-1)^{i-k}\\binom{i}{k}\\alpha (i)
\\]
然后对于\\(\\alpha (x)\\),可以直接用\\(Hash\\_Table\\)求。
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define int long long
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch==\'-\') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-\'0\';x*=f;
}
void print(int x) {
if(x<0) x=-x,putchar(\'-\');
if(!x) return ;print(x/10),putchar(x%10+\'0\');
}
void write(int x) {if(!x) putchar(\'0\');else print(x);putchar(\'\\n\');}
#define maxn 2000050
int binom(int n,int m) {
int res=1;for(int i=1;i<=m;i++) res=res*(n-i+1);
for(int i=1;i<=m;i++) res=res/i;return res;
}
int n,k,a[maxn][7];
const int mod=1e6+19,base=10;
struct Hash_Table {
int head[mod+1],nxt[maxn],val[maxn][7],sum[maxn],tot;
int insert(int p,int s) {
int hs=0;
for(int i=0;i<6;i++) if((s>>i)&1) hs=(hs*base+a[p][i+1])%mod;
for(int i=head[hs];i;i=nxt[i]) {
int cnt=0,bo=1;//write(hs);
for(int j=1;j<=6;j++) if((s>>(j-1))&1) if(val[i][++cnt]!=a[p][j]) bo=0;
if(bo) return sum[i]++;
}
nxt[++tot]=head[hs],head[hs]=tot;val[tot][0]=0;
for(int i=1;i<=6;i++) if((s>>(i-1))&1) val[tot][++val[tot][0]]=a[p][i];
sum[tot]++;return 0;
}
void clear() {
tot=0;memset(head,0,sizeof head);
memset(sum,0,sizeof sum);
}
}Hash;
int calc(int s) {
int l=__builtin_popcount(s),ans=0;
if(l<k) return 0;
Hash.clear();
for(int i=1;i<=n;i++) ans+=Hash.insert(i,s);
ans*=(((l-k)&1)?-1:1)*binom(l,k);
//if(ans) printf("%d %d\\n",s,ans);
return ans;
}
signed main() {
read(n),read(k);
for(int i=1;i<=n;i++) for(int j=1;j<=6;j++) read(a[i][j]);
int ans=0;
for(int i=0;i<(1<<6);i++) ans+=calc(i);
write(ans);//Hash.debug();
//cerr << (double) clock()/CLOCKS_PER_SEC << endl;
return 0;
}