jzoj3632 【汕頭市選2014】舞伴(狀壓dp)
阿新 • • 發佈:2019-02-19
【汕頭市選2014】舞伴(perm)
Description
N 個男孩,N 個女孩,男孩和女孩可能是朋友,也可能不是朋友。現在要組成N 對舞伴,要求每對舞
伴都是一男一女,且他們是朋友。
統計不同配對方案的數量,因為結果很大,所以只要求除以M 的餘數。
Input
第1 行,2 個整數N,M。接下來N 行,每行N 個整數Aij,表示第i 個男孩和第j 個女孩的關係。如果他們是朋友,則Aij = 1,否則Aij = 0。
Output
1 個整數,表示所求的值。
Sample Input
3 1000000000
1 1 1
1 1 1
1 1 1
Sample Output
6
Data Constraint
• 對於50% 的資料,N <= 9;
• 對於100% 的資料,1 <= N <= 20, 1 <= M <= 10^9; 0 <= Aij <= 1。
分析:狀壓dp,還挺水。。
程式碼
#include <cstdio>
#define M 1100000
using namespace std;
int n,l[22],r[22];
long long m,f[M];
int bin[22],a[22][22],num[M];
int get(int x)
{
int s=0;
while (x>0)
{
if (x%2==1) s++;
x/=2;
}
return s;
}
int main()
{
// freopen("perm.in","r",stdin);
// freopen("perm.out","w",stdout);
scanf("%d%d",&n,&m);
bin[1]=1;
for (int i=2;i<=21;i++)
bin[i]=bin[i-1]*2;
for (int i=1;i<=bin[n+1]-1;i++)
num[i]=get(i);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
for (int i=1;i<=n;i++)
{
l[i]=l[i-1]+bin[n-i+1];
r[i]=r[i-1]+bin[i];
}
f[0]=1;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
if (a[i][j])
for (int s=l[i];s>=r[i];s--)
if (num[s]==i&&(s&bin[j])) f[s]=(f[s]+f[s-bin[j]])%m;
}
printf("%lld",f[l[n]]);
fclose(stdin);
fclose(stdout);
}