2018SD省队集训R2 D4

T3

这里写图片描述

题解

我们看到最后的柿子差不多是个多项式定理的样子
不过这个实数的t次方怎么求期望呢?用积分,x^n的不定积分怎么算?
当n≠-1时
∫x^ndx=1/(n+1)*x^(n+1)+C
当n=-1时
∫x^ndx=lnx+C
那么这个求出来是面积,我们还要除以概率,也就是除以a
那么最后设E(i,t)表示 xti x i t 的概率,那么 E(i,t)=atit+1 E ( i , t ) = a i t t + 1 ,那么根据多项式定理,答案就是

ti=mi=1nE(i,ti)m!ni=1ti! ∑ ∑ t i = m ∏ i = 1 n E ( i , t i ) m ! ∏ i = 1 n t i !

这就是个多项式乘法,我们可以通过NTT求出最后a[m]表示系数,再乘一些乱七八糟的(?)就是答案
O(n^2logn)可以获得70pts

因为*国最终输了这场比赛,那么输出0可以获得100

代码

70pts(sls的代码)才不是自己懒得写

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define o 10005
using namespace std;
const ll Mod=998244353;
const ll g=3;
ll w[o],uw[o];
int rev[o];
ll ksm(ll a,ll b,ll p){
    ll ans=1;
    for(;b;b>>=1,a=a*a%p) if(b&1) ans=ans*a%p;
    return ans;
}
void init(int n,int ti){
    ll x=ksm(g,(Mod-1)/n,Mod),y;
    y=ksm(x,Mod-2,Mod);
    w[0]=uw[0]=1;
    for(int i=1;i<n;i++){
        w[i]=w[i-1]*x%Mod;
        uw[i]=uw[i-1]*y%Mod;
    }   
    for(int i=1;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(ti-1));
}
void NTT(ll *a,ll *w,int n){
    for(int i=0;i<n;i++) if(rev[i]>i) swap(a[i],a[rev[i]]);
    for(int i=2;i<=n;i<<=1){
        int m=i>>1;
        for(int j=0;j<n;j+=i)
            for(int k=0;k<m;k++){
                ll x=a[j+k+m]*w[n/i*k]%Mod;
                a[j+k+m]=(a[j+k]-x)%Mod;
                a[j+k]=(a[j+k]+x)%Mod;
            }
    }
}
int n,m;
ll a[o],b[o],A[o],fac[o],inv[o];
int main(){
        freopen("worldcup.in","r",stdin);
    freopen("worldcup.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&A[i]);
    fac[0]=inv[0]=1;
    for(ll i=1;i<=m+1;i++) fac[i]=fac[i-1]*i%Mod;
    inv[m+1]=ksm(fac[m+1],Mod-2,Mod);
    for(ll i=m+1;i>1;i--) inv[i-1]=inv[i]*i%Mod;
    int fn=1,cnt=0;
    while(fn<=m+m) fn<<=1,cnt++;
    init(fn,cnt);
    a[0]=1;
    ll invf=ksm(fn,Mod-2,Mod);
    for(int i=1;i<=n;i++){
        ll ai=1;
        b[0]=1;
        for(int j=1;j<=m;j++){
            ai=ai*A[i]%Mod;
            b[j]=inv[j+1]*ai%Mod;   
        }
        for(int j=m+1;j<=fn;j++) b[j]=0;
        NTT(a,w,fn);NTT(b,w,fn);
        for(int j=0;j<fn;j++) a[j]=a[j]*b[j]%Mod;
        NTT(a,uw,fn);
        for(int j=0;j<=m;j++) a[j]=(a[j]*invf%Mod+Mod)%Mod;
        for(int j=m+1;j<=fn;j++) a[j]=0;
    }
    ll ans=(a[m]*fac[m]%Mod+Mod)%Mod;
    printf("%lld\n",ans);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值