Codeforces Round #175 (Div. 2)

D题, 纠结, 一开始想用组合数学的方法可是想不出怎么排列组合, 然后又准备暴力结果发现普通暴力在n=15的时候就不知道要运行多少时间。。。

于是去学习了一个 中途相遇的 搜索算法,快了很多, n=15的那组数据也可以在20s内跑完.

其实这个算法就是将 n^n 的复杂度变成了 2*n^(n/2) ,  可以快很多....

本质就是将整个搜索过程分成两半来搜。

 

D. Permutation Sum
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Permutation 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


#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
#define MOD 1000000007
typedef __int64 LL;

int n;
int n1,n2;
int g1[20],g2[20];
int key;
int cnt1,cnt2;
LL sum1[1<<17],sum2[1<<17];

int pan(int i,int k)
{
    int sum=0;
    while(i)
    {
        sum += i&1;
        i=i>>1;;
    }
    return sum==k;
}

void dfs1(int s)
{
    if(s>n1)
    {
        sum1[key]++;
        return ;
    }
    for(int i=0;i<cnt1;i++)
    {
        int tmp=g1[i];
        if(g1[i]==-1) continue;
        int tmp1=(tmp+s-2)%n+1;
        if(key & ( 1<<(tmp1-1) ) ) continue;
        key |= ( 1<<(tmp1-1) );
        g1[i]=-1;
        dfs1(s+1);
        g1[i]=tmp;
        key ^= ( 1<<(tmp1-1) );
    }
}
void dfs2(int s)
{
    if(s>n)
    {
        sum2[key]++;
        return ;
    }
    for(int i=0;i<cnt2;i++)
    {
        int tmp=g2[i];
        if(g2[i]==-1) continue;
        int tmp1=(tmp+s-2)%n+1;
        if(key & ( 1<<(tmp1-1) ) ) continue;
        key |= ( 1<<(tmp1-1) );
        g2[i]=-1;
        dfs2(s+1);
        g2[i]=tmp;
        key ^= ( 1<<(tmp1-1) );
    }
}

int main()
{
    for(int i=1;i<=16;i++)
    {
        n=i;
        n1=n/2; n2=n-n1;
        LL ans=0;
        for(int i=0;i<=(1<<n)-1;i++)
        {
            if(pan(i,n1)==0) continue;
            cnt1=0; cnt2=0;
            for(int j=0;j<n;j++)
            {
                if( (1<<j)&i ) g1[cnt1++]=j+1;
                else g2[cnt2++]=j+1;
            }
            memset(sum1,0,sizeof(sum1));
            memset(sum2,0,sizeof(sum2));
            key=0; // 主要用来记录c的情况...
            dfs1(1);
            key=0;
            dfs2(n1+1);
            for(int j=0;j<=(1<<n)-1;j++)
            {
                int tmp=j^((1<<n)-1);
                ans=(ans+(sum1[j]*sum2[tmp])%MOD)%MOD;
            }
        }
        for(int i=1;i<=n;i++)
            ans=(ans*i)%MOD;
        printf("%I64d,",ans);
    }
    return 0;
}

/*#include <stdio.h>

int g[20]={0,1,0,18,0,1800,0,670320,0,734832000,0,890786230,0,695720788,0,150347555,0};

int main()
{
    int n;
    scanf("%d",&n);
    printf("%d",g[n]);
}*/

 

posted @ 2013-04-15 17:13  chenhuan001  阅读(425)  评论(0编辑  收藏  举报