题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=3198
题解
考虑容斥,答案就是 ∑ i = k n ( i k ) × \sum_{i=k}^n\binom{i}{k}\times ∑i=kn(ki)×至少 i i i个相同的方案数。这个用hash统计就可以了。
代码
#include <cstdio>
#include <cstring>
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int maxn=1000000;
const int maxv=1<<30;
struct data
{
int v[6];
};
namespace ht
{
const int mod=1000003;
int now[mod+10],tot,pre[maxn+10],cnt[maxn+10];
data val[maxn+10];
int clear()
{
memset(now,0,sizeof now);
tot=0;
return 0;
}
int gethash(data d,int ch)
{
int p=0;
for(int i=0; i<6; ++i)
{
if(ch&(1<<i))
{
p=(1ll*p*maxv+d.v[i])%mod;
}
}
return p;
}
int get_add(data d,int ch)
{
int p=gethash(d,ch);
for(int i=now[p]; i; i=pre[i])
{
int flag=0;
for(int j=0; j<6; ++j)
{
if((ch&(1<<j))&&(val[i].v[j]!=d.v[j]))
{
flag=1;
break;
}
}
if(!flag)
{
++cnt[i];
return cnt[i]-1;
}
}
pre[++tot]=now[p];
now[p]=tot;
val[tot]=d;
cnt[tot]=1;
return 0;
}
}
data d[maxn+10];
int n,k;
long long ans;
int C(int a,int b)
{
int res=1;
for(int i=1; i<=b; ++i)
{
res=res*(a-i+1)/i;
}
return res;
}
int main()
{
n=read();
k=read();
for(int i=1; i<=n; ++i)
{
for(int j=0; j<6; ++j)
{
d[i].v[j]=read();
}
}
for(int i=0; i<1<<6; ++i)
{
int cnt=0;
for(int j=0; j<6; ++j)
{
if(i&(1<<j))
{
++cnt;
}
}
if(cnt<k)
{
continue;
}
ht::clear();
for(int j=1; j<=n; ++j)
{
ans=ans+(((cnt-k)&1)?-1:1)*C(cnt,k)*ht::get_add(d[j],i);
}
}
printf("%lld\n",ans);
return 0;
}