zoukankan      html  css  js  c++  java
  • codeforces 429 On the Bench dp+排列组合 限制相邻元素,求合法序列数。

    限制相邻元素,求合法序列数。
    /**
    题目:On the Bench
    链接:http://codeforces.com/problemset/problem/840/C
    题意:求相邻的元素相乘不为平方数的方案数(这里求得是排列方案数,所以哪怕数相同,只要位置不同也算一种方案)
    
    思路 :
    每个数可以表示为  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]*mul 就是最终答案了; mul表示每一组的数都可以排列;哪怕是相同的数由于位置不同,仍然可以排列;
    
    转自:http://www.cnblogs.com/orz010orz/p/7398692.html
    
    */
    #include<bits/stdc++.h>
    #define LL long long
    #define ms(x,y) memset(x,y,sizeof x)
    #define ls(i) seg[i].lc
    #define rs(i) seg[i].rc
    using namespace std;
    typedef pair<int,int> pii;
    const int maxn = 305;
    const int mod = 1e9+7;
    const LL INF = 1e12 + 10;
    int cnt[maxn], sum[maxn];
    LL dp[maxn][maxn];
    LL c[305][305];
    int a[maxn], n, m, vis[maxn];
    int fac[maxn];
    void init(){
        c[0][0] = 1;
        for(int i = 1; i < maxn; i++){
            c[i][0] = 1;
            for(int j = 1; j <= i; j++){
                c[i][j] = (c[i-1][j-1]+c[i-1][j])%mod;
            }
        }
        fac[0] = 1;
        for(int i = 1; i < maxn; i++) fac[i] = (LL)fac[i-1]*i%mod;
    }
    bool ok(LL x)
    {
        LL lo = 1, hi = 1e9, mi, ans = 0;
        while(lo<=hi){
            mi = (lo+hi)/2;
            if(mi*mi>=x) hi = mi-1, ans = mi;
            else lo = mi+1;
        }
        return ans*ans==x;
    }
    int cmp(int a,int b)
    {
        return a>b;
    }
    void getCnt()
    {
        m = 0;
        ms(cnt,0);
        ms(vis,0);
        for(int i = 1; i <= n; i++){
            if(vis[i]) continue;
            ++m;
            cnt[m]++;
            for(int j = i+1; j <= n; j++){
                if(vis[j]) continue;
                ///judge a[i], a[j] is equal?
                if(ok(1LL*a[i]*a[j])){///judge(i,j)
                    cnt[m]++;
                    vis[j] = 1;
                }
            }
        }
    }
    int main()
    {
        init();
        while(scanf("%d",&n)==1)
        {
            for(int i = 1; i <= n; i++){
                scanf("%d",&a[i]);
            }
            getCnt();
            n = m;
            LL mul = 1;
            for(int i = 1; i <= n; i++){
                sum[i] = sum[i-1]+cnt[i];
                mul = mul*fac[cnt[i]]%mod;
            }
            ms(dp,0);
            if(cnt[1]>0)
                dp[1][cnt[1]-1] = 1;
            for(int i = 2; i <= n; i++){
                for(int j = 0; j <= sum[i]-1; j++){
                    if(!dp[i-1][j]) continue;
                    for(int k = 1; k <= cnt[i]; k++){
                        for(int z = 0; z <= k&&z<=j; z++){
                            LL res = dp[i-1][j]*c[j][z]%mod*c[cnt[i]-1][k-1]%mod*c[sum[i-1]+1-j][k-z]%mod;
                            dp[i][j-z+cnt[i]-k] = (dp[i][j-z+cnt[i]-k]+res)%mod;
                        }
                    }
                }
            }
            cout<<dp[n][0]*mul%mod<<endl;
        }
        return 0;
    }
  • 相关阅读:
    js对象
    _proto_和prototype区别
    手写自己的Vuex
    limitPNG压缩图片
    swiper兼容性ie浏览器出现的问题
    postcss-pxtorem
    【Other】Win10防火墙放行Docker(WSL2)端口
    docker容器内使用apt-get报错
    docker+mysql
    docker部署+验证码错误
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7419091.html
Copyright © 2011-2022 走看看