zoukankan      html  css  js  c++  java
  • 51nod 抽卡大赛

    抽卡大赛

    链接

    分析:

      $O(n^4)$的做法比较好想,枚举第i个人选第j个,然后背包一下,求出有k个比他大的概率。

      优化:

      第i个人,选择一张卡片,第j个人选的卡片大于第i个人的概率是$p_j$,那么答案的生成函数是:

      $prod limits _{j = 1}^{n} [j != i]((1 - p_j) + p_jx)$

      那么可以将所有人选的卡片按A排序,每次移动,只有一个多项式发生改变,改变的只有一个人,每个人只有一个长度为2的多项式,乘和除都可以做到$O(n)$。

    代码: 

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cctype>
    #include<cmath>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<bitset>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 205, mod = 1e9 + 7, inv100 = 570000004;
    
    struct Node { int A, G, P, id; } a[N * N];
    bool operator < (const Node& x,const Node &y) { return x.A > y.A; }
    int f[N], v[N], sump[N], ans[N], n;
    
    int ksm(int a,int b) {
        int res = 1;
        while (b) {
            if (b & 1) res = 1ll * res * a % mod;
            a = 1ll * a * a % mod;
            b >>= 1;
        }
        return res;
    }
    void Div(int p) {
        int inv = ksm(1 - p, mod - 2);
        f[0] = 1ll * f[0] * inv % mod;
        for (int i = 1; i < n; ++i) f[i] = 1ll * (f[i] - 1ll * p * f[i - 1] % mod) * inv % mod;
    }
    void Mul(int p) {
        for (int i = n - 1; i >= 0; --i) 
        f[i] = (1ll * f[i] * (mod + 1 - p) % mod + 1ll * f[i - 1] * p % mod) % mod;
    }
    int main() {
        n = read();int cnt = 0;
        for (int i = 1; i <= n; ++i) {
            int m = read(), sum = 0;
            for (int j = 1; j <= m; ++j) {
                a[++cnt].id = i;
                a[cnt].A = read(), a[cnt].G = read(), a[cnt].P = read(); sum += a[cnt].P;
                a[cnt].G = 1ll * (100 - a[cnt].G) * inv100 % mod;
            }
            for (int j = 0; j < m; ++j) 
                a[cnt - j].P = 1ll * a[cnt - j].P * ksm(sum, mod - 2) % mod;
        }
        for (int i = 0; i < n; ++i) v[i] = read();
        sort(a + 1, a + cnt + 1);
        f[0] = 1;
        for (int i = 1; i <= cnt; ++i) {
            if (a[i].id != a[i - 1].id) {
                Div(sump[a[i].id]);
                Mul(sump[a[i - 1].id]);
            }
            for (int j = 0; j < n; ++j) 
                ans[a[i].id] = (ans[a[i].id] + 1ll * f[j] * v[j] % mod * a[i].P % mod * a[i].G) % mod;
            sump[a[i].id] = (sump[a[i].id] + a[i].P) % mod;
        }
        for (int i = 1; i <= n; ++i) printf("%d
    ", (ans[i] + mod) % mod);
        return 0;
    }
  • 相关阅读:
    递归
    HDU_oj_2041 超级楼梯
    树与森林——树与森林的遍历
    HUD_oj_2040 亲和数
    HDU_oj_2039 判定三角形
    HDU_oj_2037 今年暑假不AC
    多边形面积
    HDU_oj_2036 改革春风吹满地(多边形面积)
    【转发】【composer】composer 命令行介绍
    【chm】【windows】win7下chm打开不显示内容
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10645976.html
Copyright © 2011-2022 走看看