• [51Nod1850] 抽卡大赛


    link

    $solution:$

    朴素 $dp$,暴力枚举选择 $i$ 号人的第 $j$ 张卡片,朴素 $dp$ 即可,时间复杂度 $O(n^4)$ 。

    考虑对于朴素 $dp$ 的优化,发现其实是一个背包卷积的过程,考虑按 $A$ 值从大到小依次加入,每次维护新的 $P$ 值可以做到 $O(1)$ 。

    设计生成函数 $F(x)$ 表示将 $1-n$ 的所有多项式卷在一起的答案,每次只要维护多项式除法与乘法即可,而对于每个多项式都是形如 $ax+b$ 的形式,所以直接暴力维护即可。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define mod 1000000007
    #define int long long
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    const int MAXN=401;
    struct node{
        int val,id,res,p;
    }g[MAXN*MAXN];
    inline int ksm(int a,int b){
        int ans=1;
        while(b){
            if(b&1) ans*=a,ans%=mod;
            a*=a,a%=mod;
            b>>=1;
        }return ans;
    }
    int n,tot,F[MAXN],G[MAXN],p[MAXN];
    inline void mul(int x1,int x0){
        if(!x1) return;
        for(int i=0;i<=n;i++) G[i]+=F[i]*x0,G[i]%=mod,G[i+1]+=F[i]*x1,G[i+1]%=mod;
        for(int i=0;i<=n;i++) F[i]=G[i];memset(G,0,sizeof(G));return;
    }
    int Mod(int x){return ((x%mod)+mod)%mod;}
    inline void Div(int x1,int x0){
        if(!x1) return;int Inv=ksm(x1,mod-2);
        for(int i=n-1;i>=0;i--) G[i]=(Inv*F[i+1])%mod,F[i]=Mod(F[i]-x0*G[i]);
        for(int i=0;i<=n;i++) F[i]=G[i];memset(G,0,sizeof(G));return;
        return;
    }
    bool cmp(node x1,node x2){return x1.val>x2.val;}
    int P[MAXN],Ans[MAXN],v[MAXN];
    signed main(){
    //    freopen("51nod_1850_11_in.txt","r",stdin);
        n=read();int inv100=ksm(100,mod-2);
        for(int i=1;i<=n;i++){
            int num=read();
            int sum=0;
            int L=++tot,R=0;
            for(int j=1;j<=num;j++){
                g[++tot].id=i;
                g[tot].val=read(),g[tot].res=((100-read())*inv100)%mod,g[tot].p=read();
                sum+=g[tot].p;
                R=tot;
            }
            for(int j=L;j<=R;j++) g[j].p=(g[j].p*ksm(sum,mod-2))%mod;
        }
        for(int i=1;i<=n;i++) v[i]=read();
        F[0]=1;
        sort(g+1,g+tot+1,cmp);
        for(int i=1;i<=tot;i++){
            int id=g[i].id;
            Div(P[id],Mod(1-P[id]));
            P[id]+=g[i].p,P[id]=Mod(P[id]);P[id]=Mod(P[id]);
            for(int k=0;k<n;k++) Ans[id]+=Mod(Mod(Mod(F[k]*v[k+1])*g[i].res)*g[i].p),Ans[id]=Mod(Ans[id]);
            mul(P[id],Mod(1-P[id]));
        }
        for(int i=1;i<=n;i++) printf("%d
    ",Ans[i]);return 0;
    }
    View Code
  • 相关阅读:
    C#判断闰年
    C#计算时间,107653秒是几天几小时几分钟几秒?
    两个值交换,不使用第三个中间变量做缓存。实现方法
    element UI dialog 固定高度 且关闭时清空数据
    JS
    PHP
    element UI 上传文件成功后
    windows环境安装vue-cli及webpack并创建vueJs项目
    PHP
    mysql点滴记录 三 (基础操作)
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/11336235.html
Copyright © 2020-2023  润新知