#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,S,T,A[18];
ll dp[1<<18][18];
ll dfs(int s,int a){
if(s==T){
int b=(a+1)%n,c=(a+n-1)%n;
return b!=A[0]&&c!=A[0];
}ll &ans=dp[s][a];
if(~ans)return ans;ans=0;
int b=(a+1)%n,s1=0,s2=T;
s2^=1<<a^1<<b;
//我们用集合s1,s2来表示除了边a,b以外的点(s1,s2分居于边a-b两侧)
//如果我们的集合s中既有s1中的元素也有s2中的元素说明这条边和其他的边相交了
while(a!=b){
if(!(s&1<<b))
if((s1&s)&&(s2&s))
ans+=dfs(s|1<<b,b);
s1^=1<<b;b=(b+1)%n;s2^=1<<b;
}
return ans;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=0;i<m;i++){scanf("%d",A+i);A[i]--;}
memset(dp,-1,sizeof(dp));
S=0;T=(1<<n)-1;
for(int i=0;i<m;i++)S|=1<<A[i];
cout<<dfs(S,A[m-1])<<'\n';
}
SRM574 Div1 450
最新推荐文章于 2017-07-10 15:04:49 发布