这里提供一个与其他题解不同的做法(不会被卡/xyx)
首先我们设res表示至少有i个相同泉水的方案,ans表示恰好i个相同泉水的方案,我们可以发现这个式子(和其他题解差不多)
ans[i]=res[i]−∑
j=i+1
6
(
i
j
)×ans[j]
然后我们考虑求res,发现我们枚举每一个2
k
按照关键字来排序后连续的一段相同的可以计入答案,这样明显跑不过去。
这时候有人可能要说用hash了,但是不,我们可以直接排序
发现一共就6∗n个数,所以我们可以把数离散化一下,值域范围很小,考虑基数排序。
按照每个关键字排序+查找,常数优化小技巧:多用memset和memcpy
让我们计算一下复杂度O(64×n×6)最后那个6还跑不满(但是基数排序要4个循环)复杂度还是把别人的log+大常数吊起来大
目前是rank2(没有专门卡常,不知道rank1是怎么写的/kk)
下面是代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
char gc()
{
static char buf[1<<16],s,t;
if(st)
{
t=(s=buf)+fread(buf,1,1<<16,stdin);
if(st)return EOF;
}
return s++;
}
#define getchar gc
int read()
{
char c;
int w=1;
while((c=getchar())>'9'||c<'0')if(c=='-')w=-1;
int ans=c-'0';
while((c=getchar())>='0'&&c<='9')ans=(ans<<1)+(ans<<3)+c-'0';
return answ;
}
int n,m;
const int xx=1e5+5;
int a[xx][7];
int lsh[xx6],c[100];
ll ans[xx];
int C[8][8];
vector<int>v[100];
int T[xx6],id[xx],nid[xx];
signed main(){
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
for(int i=0;i<64;i++)
for(int j=0;j<6;j++)if((i>>j&1))c[i]+=1,v[i].push_back(j+1);
for(int i=0;i<=7;i++)C[i][0]=1;
for(int i=1;i<=7;i++)
for(int j=1;j<=i;j++)C[i][j]=C[i-1][j]+C[i-1][j-1];
n=read();
m=read();
int tot=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=6;j++)a[i][j]=lsh[tot]=read();
sort(lsh+1,lsh+tot+1);
tot=unique(lsh+1,lsh+tot+1)-lsh-1;
for(int i=1;i<=n;i)
for(int j=1;j<=6;j++)a[i][j]=lower_bound(lsh+1,lsh+tot+1,a[i][j])-lsh;
for(int t=6;t>=0;t--)
{
for(int j=0;j<64;j++)//这两个加在一起一共64
{
if(c[j]t)
{
for(int i=1;i<=n;i++)id[i]=i;//排名为i的是哪个
for(int k=0;k<t;k++)
{
int w=v[j][k];
memset(T,0,sizeof(T[0])(tot+1));
for(int i=1;i<=n;i++)T[a[i][w]];
for(int i=1;i<=tot;i)T[i]+=T[i-1];
for(int i=n;i>=1;i--)nid[T[a[id[i]][w]]--]=id[i];
memcpy(id,nid,sizeof(id[0])(n+1));//绝对跑过,也最多就只有153600000
}
for(int i=1;i<=n;i++)
{
int tot=1;
while(1)
{
if(in)break;
int vs=1;
for(int k=0;k<t;k++)
{
int w=v[j][k];
if(a[id[i]][w]!=a[id[i+1]][w]){vs=0;break;}
}
if(vs)tot++,i++;
else break;
}
ans[t]+=(1lltot(tot-1))/2;
}
}
}
for(int k=t+1;k<=6;k++)ans[t]-=ans[k]*C[k][t];
if(t==m)return cout<<ans[t]<<"\n",0;
}
return 0;
}