zoukankan      html  css  js  c++  java
  • Codeforces Round #429 (Div. 2) E. On the Bench

    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    A year ago on the bench in public park Leha found an array of n numbers. Leha believes that permutation p is right if for all 1 ≤ i < n condition, that api·api + 1 is not perfect square, holds. Leha wants to find number of right permutations modulo 109 + 7.

    Input

    First line of input data contains single integer n (1 ≤ n ≤ 300) — length of the array.

    Next line contains n integers a1, a2, ... , an (1 ≤ ai ≤ 109) — found array.

    Output

    Output single integer — number of right permutations modulo 109 + 7.

    Examples
    Input
    3
    1 2 4
    Output
    2
    Input
    7
    5 2 4 2 4 1 1
    Output
    144
    Note

    For first example:

    [1, 2, 4] — right permutation, because 2 and 8 are not perfect squares.

    [1, 4, 2] — wrong permutation, because 4 is square of 2.

    [2, 1, 4] — wrong permutation, because 4 is square of 2.

    [2, 4, 1] — wrong permutation, because 4 is square of 2.

    [4, 1, 2] — wrong permutation, because 4 is square of 2.

    [4, 2, 1] — right permutation, because 8 and 2 are not perfect squares.

    题意 :求相邻的元素相乘不为平方数的方案数(a[0]=a[1]=1, 视 a[0] 与 a[1]  不同)

    思路 :

        每个数可以表示为  p1^a1 * p2^a2 * .....

        如果 两个数A,B相乘为平方数 则   a1%2 = a1' %2  ,  a2%2 = a2'%2 .....

        即 对应质因子的幂次 奇偶性相同 这样就可以划分出T组 

        然后题目就转化为 T种物品 相同种类物品不能放在相邻 求方案数

        这题就变成原题 :https://csacademy.com/contest/archive/task/distinct_neighbours/statement/

                http://acm.hdu.edu.cn/showproblem.php?pid=6116

        做法为dp

        dp [ i ] [ j ]  表示  插入第 i 组的物品 出现了 左右为相同物品的空隙个数为 j   的方案数

        那 dp [ T ]  [ 0 ]  就是最终答案了

        附: cs官方题解 (原题的题解)

          First we group all the distinct values in the array. Then we can solve the problem using dynamic programming:

          Let dp[i][j] = the number of distinct arrays that can be obtained using the elements of the first i groups such that there are exactly j pairs of consecutive positions having the same value. The answer can be found in dp[distinctValues][0].

          Now let's say the sum of frequences of the first i values is X. This means the arrrays we can build using the elements from these i groups have size X, so we can insert the elments of group i + 1 in X + 1 gaps: before the first element, after the last, and between any two consecutive. We can fix the number k of gaps where we want to insert at least one element from group i + 1, but we also need to fix the number l of these k gaps which will be between elements that previously had the same value. State dp[i][j] will update the state dp[i + 1][j - l + frequence[i + 1] - k].

          The number of ways of choosing k gaps such that exactly l are between consecutive elements having the same value can be computed easily using combination formulas. We  are left with finding out the number of ways of inserting frequence[i + 1] elements in k gaps. This is also a classical problem with a simple answer: Comb(frequence[i + 1] - 1, k - 1). 

        具体转移方程见代码 :

        

        

    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <math.h>
    #include <set>
    #include <map>
    #include <stack>
    #include <queue>
    #include <vector>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    
    #define mp make_pair
    #define pb push_back
    #define mes(a,b) memset(a,b,sizeof(a))
    #define mes0(a) memset(a,0,sizeof(a))
    #define lson l,mid,pos<<1
    #define rson mid+1,r,pos<<1|1
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define fi first
    #define se second
    #define sss(a) a::iterator
    #define all(a) a.begin(),a.end()
    
    using namespace std;
    
    typedef double DB;
    typedef long long LL;
    typedef pair<int,int> pii;
    typedef pair<long long ,int> pli;
    typedef pair<int,long long > pil;
    typedef pair<string,int> psi;
    typedef pair<long long ,long long > pll;
    
    const int inf = 0x3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double pi = acos(-1.0);
    const int maxn = 100000+10;
    const int mod = 1e9+7;
    LL dp[500][500];
    LL C[500][500];
    LL fact[500];
    int cnt[500];
    int a[500];
    int vis[500];
    int sz;
    int check(LL x)
    {
        LL l=1,r=1e9;
        LL now=l;
        while (l<=r){
            LL mid=(l+r)>>1;
            if (mid*mid<=x)now=mid,l=mid+1;
            else r=mid-1;
        }
        return now*now==x;
    }
    inline LL M(LL x)
    {
        return x%mod;
    }
    void init()
    {
        C[0][0]=1;
        fact[0]=1;
        for (int i=1;i<=300;i++){
            C[i][0]=1;
            for (int j=1;j<=i;j++){
                C[i][j]=M(C[i-1][j]+C[i-1][j-1]);
            }
        }
        for (int i=1;i<=300;i++)fact[i]=M(fact[i-1]*i);
    }
    void slove()
    {
        dp[0][cnt[0]-1]=1;
        int lim=cnt[0];
        for (int i=1;i<sz;i++){
            for (int j=0;j<lim;j++){  /// dp[i-1][j]
                for (int k=0;k<cnt[i];k++){/// group[i]分成k+1组 ,cnt[i]-1-k个空隙
                    for (int m=0;m<=min(j,k+1);m++){ /// 选了m个左右相同的空隙插入
                        dp[i][j+cnt[i]-1-k-m]=M(dp[i][j+cnt[i]-1-k-m]+dp[i-1][j]*C[cnt[i]-1][k]%mod*C[j][m]%mod*C[lim-1-j+2][k+1-m]);
                    }
                }
            }
            lim+=cnt[i];
        }
        LL ans=dp[sz-1][0];
        for (int i=0;i<sz;i++){
            ans*=fact[cnt[i]];
            ans%=mod;
        }
        cout<<ans<<endl;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int n;
        scanf("%d",&n);
        for (int i=0;i<n;i++){
            scanf("%d",a+i);
        }
        for (int i=0;i<n;i++){
            if (vis[i]==0){
                for (int j=i;j<n;j++){
                    if (check(1LL*a[i]*a[j])){
                        cnt[sz]++;
                        vis[j]=1;
                    }
                }
                sz++;
            }
        }
        init();
        slove();
        return 0;
    }
  • 相关阅读:
    jQuery 原理的模拟代码 0 目录
    非真实渲染技术(NPR)1.卡通渲染
    [翻译]延迟着色(1)
    Bloom原理
    bloom, Fake HDR, True HDR(转)
    [翻译]延迟着色(2)
    STL中map与hash_map容器的选择
    将文本转换成IDirect3DTexture9
    D3D中的AGP内存、系统内存、显存的理解
    如何加强角色渲染的真实感(self shadow + subsurface scattering + rim lighting)
  • 原文地址:https://www.cnblogs.com/orz010orz/p/7398692.html
Copyright © 2011-2022 走看看