您的位置:首页 > 其它

【汕头市选2014】舞伴(perm)

2017-03-01 20:44 260 查看

题目

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。

题解

一眼状压,但是发现普通状压是2n∗n2的会超时

然后发现如果一个二进制可能可以被转移,那么一定有i个位是1

所以先把所有二进制按照1的个数排序再做就不会tle了

贴代码

var
i,j,k,n,t:longint;
f:array[0..21,0..1100000]of int64;
war:array[0..1100000,1..2]of longint;
a:array[0..25,0..25]of longint;
op,ed:array[0..25]of longint;
x,y,z,m:int64;
procedure qsort(l,r:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=war[(i+j) div 2,2];
repeat
while war[i,2]<mid do inc(i);
while war[j,2]>mid do dec(j);
if i<=j then
begin
war[0]:=war[i];
war[i]:=war[j];
war[j]:=war[0];
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
begin
//assign(input,'t1.in'); reset(input);
assign(input,'perm.in'); reset(input);
assign(output,'perm.out'); rewrite(output);
readln(n,m);
for i:=1 to n do
begin
for j:=1 to n do
begin
read(k);
if k=0 then continue;
inc(a[i,0]);
a[i,a[i,0]]:=j;
end;
readln;
end;
for i:=1 to 1<<n-1 do
begin
war[i,1]:=i;
k:=0;
for j:=1 to n do
if 1<<(j-1) and i<>0 then inc(k);
war[i,2]:=k;
end;
qsort(1,1<<n-1);
op[0]:=0;
ed[0]:=0;
op[1]:=1;
for i:=2 to 1<<n-1 do
if war[i,2]<>war[i-1,2] then
begin
ed[war[i-1,2]]:=i-1;
op[war[i,2]]:=i;
end;
ed[war[i,2]]:=i;
f[0,0]:=1;
war[0,1]:=0;
for i:=1 to n do
for t:=op[i-1] to ed[i-1] do
begin
j:=war[t,1];
for k:=1 to a[i,0] do
begin
x:=(1<<(a[i,k]-1)) and j;
y:=(1<<(a[i,k]-1)) xor j;
if x and j=0 then
f[i,y]:=(f[i,y]+f[i-1,j]) mod m;
end;
end;
writeln(f[n,1<<n-1]);
close(input); close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: