开始补状压DP
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<queue> 6 #define inc(i,l,r) for(int i=l;i<=r;i++) 7 #define dec(i,l,r) for(int i=l;i>=r;i--) 8 #define link(x) for(edge *j=h[x];j;j=j->next) 9 #define mem(a) memset(a,0,sizeof(a)) 10 #define ll long long 11 #define succ(x) (1<<x) 12 #define NM 22 13 using namespace std; 14 int read(){ 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 17 while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); 18 return x*f; 19 } 20 bool a[NM][NM]; 21 int n,m; 22 ll d[succ(NM)],inf; 23 int main(){ 24 freopen("perm.in","r",stdin); 25 freopen("perm.out","w",stdout); 26 n=read();inf=read(); 27 inc(i,1,n) 28 inc(j,1,n)a[i][j]=read(); 29 d[0]++; 30 inc(t,0,succ(n)-1){ 31 int i=__builtin_popcount(t)+1; 32 inc(j,1,n) 33 if(!(t&succ(j-1))&&a[i][j]) 34 (d[t|succ(j-1)]+=d[t])%=inf; 35 } 36 printf("%lld\n",d[succ(n)-1]); 37 return 0; 38 }