[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\n",Ans[i]);return 0;
}
View Code

 

posted @ 2019-08-11 19:18  siruiyang_sry  阅读(240)  评论(0编辑  收藏  举报