zoukankan      html  css  js  c++  java
  • 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]);
    }*/
  • 相关阅读:
    ES6解构赋值
    ES6中的Symbol类型
    两个列表合并成字典
    python关于列表转为字典的两个小方法
    break、continue和return的使用
    进度条的实现
    md5加密
    dict字典方法
    用户相关的文件、解析以及命令的使用
    linux的根目录
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/3022476.html
Copyright © 2011-2022 走看看