136 lines
3.3 KiB
C++
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;
|
|
} |