Files
SH-Quizzes/ACMOJ-1018.cpp
2023-12-23 22:23:48 +08:00

136 lines
3.3 KiB
C++

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cassert>
#include<vector>
#include<random>
// #include<map>
using namespace std;
typedef long long LL;
typedef pair<int,LL> SufType;
const int maxn=1005;
int N,K,a[maxn];
bool used[maxn];
vector<int> position,number;
LL OuterPair[20][20],stk[20],Answer,TotalNotFixed,InnerPair[1<<14][20];
int hsh[(1<<14)+1];
int PreLength,SufLength;
struct Hash_SufType2LongLong
{
const static int PoolSize=17297280*3;
const static LL a=233331,b=19260817;
LL Pool[PoolSize];
int head[PoolSize],nxt[PoolSize],stv[PoolSize],CntV[PoolSize],PoolCnt=0;
inline LL& operator[](const SufType &key)
{
const LL HashValue=(key.first*a+key.second+b)%PoolSize;
// return Pool[HashValue];
int p=head[HashValue];
while(p)
{
if(stv[p]==key.first&&CntV[p]==key.second) return Pool[p];
p=nxt[p];
}
PoolCnt++;
nxt[PoolCnt]=head[HashValue];
stv[PoolCnt]=key.first;
CntV[PoolCnt]=key.second;
head[HashValue]=PoolCnt;
return Pool[PoolCnt];
}
}SufData;
void dfs(int dep,LL CurrentPair,int st)
{
if(dep==PreLength)
{
Answer+=SufData[SufType(((1<<TotalNotFixed)-1)^st,K-CurrentPair)];
return;
}
int valid=((1<<TotalNotFixed)-1)^st;
for(;valid;valid-=valid&(-valid))
{
int i=hsh[valid&(-valid)];
if((st&(1<<i))==0
&&CurrentPair+InnerPair[st][i]+OuterPair[dep][i]<=K
&&!(K>CurrentPair+(TotalNotFixed-dep)*(TotalNotFixed-dep-1)/2+(TotalNotFixed-dep)*(N-TotalNotFixed+dep)))
{
stk[dep]=number[i];
dfs(dep+1,CurrentPair+InnerPair[st][i]+OuterPair[dep][i],st|(1<<i));
}
}
}
int main()
{
#ifdef local
freopen("pro.in","r",stdin);
#endif
scanf("%d%d",&N,&K);
for(int i=1;i<=N;i++)
{
scanf("%d",&a[i]);
used[a[i]]=true;
if(a[i]==0) position.push_back(i);
assert(0<=a[i]&&a[i]<=N);
}
LL AlreadyHave=0;
for(int i=1;i<=N;i++)
for(int j=i+1;j<=N;j++)
if(a[i]!=0&&a[j]!=0&&a[i]>a[j])
AlreadyHave++;
for(int i=1;i<=N;i++)
if(!used[i])
number.push_back(i);
TotalNotFixed=position.size();
for(int i=0;i<TotalNotFixed;i++)
{
const int pos=position[i];
for(int j=0;j<TotalNotFixed;j++)
{
const int num=number[j];
for(int k=1;k<=N;k++)
if((a[k]!=0&&k<pos&&a[k]>num)||(a[k]!=0&&k>pos&&a[k]<num))
OuterPair[i][j]++;
}
}
for(int st=0;st<(1<<TotalNotFixed);st++)
for(int p=0;p<TotalNotFixed;p++)
for(int i=0;i<TotalNotFixed;i++)
if((st&(1<<i))&&number[i]>number[p])
InnerPair[st][p]++;
if(K>AlreadyHave+TotalNotFixed*(TotalNotFixed-1)/2+TotalNotFixed*(N-TotalNotFixed))
{
puts("0");
return 0;
}
for(int i=0;i<TotalNotFixed;i++) hsh[1<<i]=i;
SufLength=(TotalNotFixed+1)/2;
PreLength=TotalNotFixed-SufLength;
const int FullStatus=(1<<TotalNotFixed)-1;
for(int st=0;st<(1<<TotalNotFixed);st++)
{
if(__builtin_popcount(st)==SufLength)
{
const int PreStatus=FullStatus^st;
int p[10],pcnt=0;
for(int i=0;i<TotalNotFixed;i++)
if(st&(1<<i))
p[pcnt++]=i;
assert(pcnt==SufLength);
do
{
LL tmp=0,AlreadyProced=0;
for(int i=0;i<SufLength;i++)
{
tmp+=OuterPair[TotalNotFixed-SufLength+i][p[i]];
tmp+=InnerPair[PreStatus][p[i]];
tmp+=InnerPair[AlreadyProced][p[i]];
AlreadyProced|=1<<p[i];
}
SufData[SufType(st,tmp)]++;
} while (next_permutation(p,p+SufLength));
}
}
dfs(0,AlreadyHave,0);
printf("%lld\n",Answer);
return 0;
}