zoukankan      html  css  js  c++  java
  • Luogu P4705 玩游戏

    题目描述
    Alice 和 Bob 又在玩游戏。

    对于一次游戏,首先 Alice 获得一个长度为 ​ 的序列 ​,Bob 获得一个长度为 ​ 的序列 bb。之后他们各从自己的序列里随机取出一个数,分别设为 ​,定义这次游戏的 ​次价值为​。

    由于他们发现这个游戏实在是太无聊了,所以想让你帮忙计算对于 ​一次游戏​ 次价值的期望是多少。

    由于答案可能很大,只需要求出模 ​下的结果即可。

    输入输出格式
    输入格式:

    第一行两个整数 ​,分别表示 Alice 和 Bob 序列的长度。

    接下来一行 ​ 个数,第 ​ 个数为 ​,表示 Alice 的序列。

    接下来一行 ​ 个数,第 ​ 个数为 ​,表示 Bob 的序列。

    接下来一行一个整数 ​,意义如上所述。

    输出格式:

    共 ​ 行,第 ​ 行表示一次游戏 ​ 次价值的期望。

    输入输出样例
    输入样例#1:

    复制

    1 1
    1
    2
    3
    输出样例#1:

    复制

    3
    9
    27
    输入样例#2:

    复制

    2 8
    764074134 743107904
    663532060 183287581 749169979 7678045 393887277 27071620 13482818 125504606
    6
    输出样例#2:

    复制

    774481679
    588343913
    758339354
    233707576
    36464684
    461784746
    神仙题啊!!

    前置知识:

    生成函数。

    Taylor展开。

    NTT。

    多项式求​。

    ​次价值得期望就是​。

    用二项式定理将分子展开:

    考虑将​展开:

    我们设:

    答案就是​

    问题的关键就在于预处理出​。

    预处理出这个多项式的方法是一个经典套路(根本不会)。












    通过​的系数可以预处理出A和B。

    解释一下,最后一步变换:

    根据Taylor展开:

    ​求导如下:

    复合函数求导遵循链式法则:

    于是:

    我们再​处展开,也就是令​

    得到:

    于是我们求出​然后就可以用第​项得系数来算出​和​。

    代码(算​的逆元的时候乘爆了,调了一晚上):

    include<bits/stdc++.h>

    define ll long long

    define N 300005

    define mod 998244353

    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch'-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return xf;}

    ll n,m;
    int t;
    ll a[N],b[N];
    ll fac[N<<2],inv[N<<2];

    ll ksm(ll t,ll x) {
    ll ans=1;
    for(;x;x>>=1,t=t
    t%mod)
    if(x&1) ans=ans*t%mod;
    return ans;
    }
    ll Mod(ll a) {
    if(a<0) return a+mod;
    if(a>=mod) return a-mod;
    return a;
    }
    int rev[N<<2];
    void NTT(ll *a,int d,int flag) {
    static const ll G=3;
    int n=1<<d;
    for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<d-1);
    for(int i=0;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
    for(int s=1;s<=d;s++) {
    int len=1<<s,mid=len>>1;
    ll w=flag
    1?ksm(G,(mod-1)/len):ksm(G,mod-1-(mod-1)/len);
    for(int i=0;i<n;i+=len) {
    ll t=1;
    for(int j=0;j<mid;j++,t=tw%mod) {
    ll u=a[i+j],v=a[i+j+mid]
    t%mod;
    a[i+j]=Mod(u+v);
    a[i+j+mid]=Mod(u-v+mod);
    }
    }
    }
    if(flag-1) {
    ll inv=ksm(n,mod-2);
    for(int i=0;i<n;i++) a[i]=a[i]*inv%mod;
    }
    }

    struct poly {
    ll g[N<<2],f[N<<2];
    ll a[N<<2],ans[N<<2];
    void solve(int l,int r) {
    if(l
    r) return ;
    int len=r-l+1,mid=l+r>>1;
    solve(l,mid),solve(mid+1,r);
    int d=ceil(log2(len+1));
    for(int i=0;i<(1<<d);i++) g[i]=f[i]=0;
    g[0]=f[0]=1;
    for(int i=l;i<=mid;i++) f[i-l+1]=a[i];
    for(int i=mid+1;i<=r;i++) g[i-mid]=a[i];
    NTT(f,d,1),NTT(g,d,1);
    for(int i=0;i<(1<<d);i++) f[i]=f[i]g[i]%mod;
    NTT(f,d,-1);
    for(int i=l;i<=r;i++) a[i]=f[i-l+1];
    }
    ll inv[N<<2],A[N<<2];
    void Inverse(ll a,int d,ll f) {
    f[0]=ksm(a[0],mod-2);
    for(int s=1;s<=d;s++) {
    int len=1<<s,Len=len<<1;
    for(int i=0;i<len;i++) A[i]=a[i],A[i+len]=0;
    NTT(A,s+1,1),NTT(f,s+1,1);
    for(int i=0;i<Len;i++) f[i]=(2
    f[i]-f[i]
    f[i]%mod
    A[i]%mod+mod)%mod;
    NTT(f,s+1,-1);
    for(int i=len;i<Len;i++) f[i]=0;
    }
    }
    void DER(ll a,int n) {
    for(int i=0;i<n;i++) a[i]=a[i+1]
    (i+1)%mod;
    a[n]=a[n-1]=0;
    }
    void INT(ll a,int n) {
    for(int i=n-1;i>=0;i--) a[i+1]=a[i]
    ksm(i+1,mod-2)%mod;
    a[0]=0;
    }
    void Ln(ll *a,int d,ll f) {
    Inverse(a,d,inv);
    DER(a,1<<d);
    NTT(inv,d+1,1),NTT(a,d+1,1);
    for(int i=0;i<(1<<d+1);i++) f[i]=inv[i]
    a[i]%mod;
    NTT(f,d+1,-1);
    INT(f,1<<d);
    }
    void mian(int n,int lim,ll *orig,ll f) {
    for(int i=1;i<=n;i++) a[i]=orig[i];
    solve(1,n);
    int d=ceil(log2(lim));
    a[0]=1;
    Ln(a,d,ans);
    for(int i=1;i<=(1<<d);i++) {
    f[i]=ans[i];
    f[i]=f[i]
    ::inv[i-1]%mod;
    if(!(i&1)) f[i]=(mod-f[i])%mod;
    }
    }
    }pre[2];
    ll A[N<<2],B[N<<2];
    int main() {
    n=Get(),m=Get();
    for(int i=1;i<=n;i++) a[i]=Get();
    for(int i=1;i<=m;i++) b[i]=Get();
    t=Get();

    fac[0]=1;
    for(int i=1;i<=t;i++) fac[i]=fac[i-1]*i%mod;
    
    inv[t]=ksm(fac[t],mod-2);
    for(int i=t-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
    
    int lim=max(n,m)+t;
    pre[0].mian(n,lim,a,A);
    pre[1].mian(m,lim,b,B);
    
    int d=ceil(log2(t*2));
    A[0]=n,B[0]=m;
    for(int i=t+1;i<(1<<d);i++) A[i]=B[i]=0;
    
    
    NTT(A,d,1),NTT(B,d,1);
    


    for(int i=0;i<(1<<d);i++) A[i]=A[i]*B[i]%mod;
    NTT(A,d,-1);

    ll invnm=ksm(1ll*n*m%mod,mod-2);
    
    for(int i=1;i<=t;i++) {
        cout<<fac[i]*A[i]%mod*invnm%mod<<"
    ";
    }
    
    return 0;
    

    }

  • 相关阅读:
    中国石油昆仑加油卡
    157 01 Android 零基础入门 03 Java常用工具类01 Java异常 01 异常介绍 02 异常内容简介
    156 01 Android 零基础入门 03 Java常用工具类01 Java异常 01 异常介绍 01 Java常用工具类简介
    155 01 Android 零基础入门 02 Java面向对象 07 Java多态 07 多态知识总结 01 多态总结
    154 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 05 匿名内部类
    153 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 04 方法内部类
    152 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 03 静态内部类
    151 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 02 成员内部类
    150 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类概述 01 内部类概述
    149 01 Android 零基础入门 02 Java面向对象 07 Java多态 05 接口(重点)07 接口的继承
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10042573.html
Copyright © 2011-2022 走看看