您的位置:首页 > 其它

codeforces 285 D Permutation Sum (状态压缩DP)

2013-05-18 16:05 351 查看
题目链接: http://www.codeforces.com/problemset/problem/285/DPermutation p is an ordered set of integers p1,  p2,  ...,  pn, consisting of n distinct positive integers, each of them doesn't exceed n. We'll denote the i-th element of permutation p as pi. We'll call number n the size or the length of permutation p1,  p2,  ...,  pn.Petya decided to introduce the sum operation on the set of permutations of length n. Let's assume that we are given two permutations of length n: a1, a2, ..., an and b1, b2, ..., bn. Petya calls the sum of permutations a and b such permutation c of length n, where ci = ((ai - 1 + bi - 1) mod n) + 1 (1 ≤ i ≤ n).Operation

means taking the remainder after dividing number x by number y.Obviously, not for all permutations a and b exists permutation c that is sum of a and b. That's why Petya got sad and asked you to do the following: given n, count the number of such pairs of permutations a and b of length n, that exists permutation c that is sum of a and b. The pair of permutations x, y (x ≠ y) and the pair of permutations y, x are considered distinct pairs.As the answer can be rather large, print the remainder after dividing it by 1000000007 (109 + 7).Input
The single line contains integer n (1 ≤ n ≤ 16).Output
In the single line print a single non-negative integer — the number of such pairs of permutations a and b, that exists permutation c that is sum of a and b, modulo 1000000007 (109 + 7).Sample test(s)Input
3
Output
18
Input
5
Output
1800

题目意思是: 求3个序列满足c[i] = (a[i]+b[i]-2)%n的个数, 每个序列都是n个不同的数字。 其实就是c[i] = (a[i]+b[i])%n(范围是0---n-1)
数据<=16,状态压缩的标志啊。
解法是对于一个给定的a序列,求满足条件的bc序列个数。用状态压缩求解。
依次检查b序列那些位没有用,而且c的(the position of a + the position of b)%n也没有用。则可以继续往下搜索。
求出的是a一个序列的解。而a有n!个序列,是不是每个都要求一次呢? 很明显不是的。a的每个序列都是等价的,所以最终结果为:
ans*n!%mod. 其实这个算法还是很慢的,因为我跑n=15的时候跑了蛮久的。 预处理出来打表是可以的。

my python code:这个是状态压缩代码
ans = 0
mod = 1000000007
f = [1]*17
for i in xrange(1, 17):
f[i] = (i*f[i-1])%mod
def dfs(Id, bNum, cSum, n):
global ans
if Id == n:
ans += 1
if ans >= mod : ans -= mod
return 0
for i in xrange(n):
if bNum&(1<<i): continue
if cSum&(1<<( (Id+i)%n ) ): continue
dfs(Id+1, bNum|(1<<i), cSum|(1<<( (Id+i)%n ) ), n )

if __name__ == '__main__':
n = input()
dfs(0, 0, 0, n)
print ans*f
%mod
有了上面的代码就可以打表了:
num = [1, 18, 1800,670320,734832000,890786230,695720788,150347555]
n = input()
print 0 if not n&1 else num[n>>1]

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: