codeforces947E Perpetual Subtraction

题目:

有一个游戏,一开始有个数 x x x,每轮游戏可以在 [ 0 , x ] [0,x] [0,x]的范围内随机找到一个数 y y y,并令 x = y x=y x=y。现在给定一个长度为 n + 1 n+1 n+1的序列 p p p,对于 ∀ i ∈ [ 0 , n ] , p i \forall i \in [0,n],p_i i[0,n],pi表示一开始的数 x x x i i i的概率,问经过 m m m轮游戏后留下的数是 i i i的概率, 0 ≤ i ≤ n 0 \le i \le n 0in。给定的和要求的概率都是模998244353意义下的。

( 1 ≤ n ≤ 1 0 5 , 0 ≤ m ≤ 1 0 18 , 0 ≤ p i < 998244353 ) (1 \le n \le 10^5,0 \le m \le 10^{18},0 \le p_i < 998244353) (1n105,0m1018,0pi<998244353)

题解:

首先可以想到一个 d p dp dp,令 f k , i f_{k,i} fk,i表示第 k k k轮后留下的数是 i i i的概率,转移方程为 f k , i = ∑ j = i n f k − 1 , j 1 j + 1 \displaystyle f_{k,i}=\sum_{j=i}^nf_{k-1,j}\frac{1}{j+1} fk,i=j=infk1,jj+11

F k ( x ) F_k(x) Fk(x) { f k , n } \{f_{k,n}\} {fk,n}的生成函数,则

F k ( x ) = ∑ i = 0 ∞ f k , i x i = ∑ i = 0 ∞ ∑ j = i n f k − 1 , j 1 j + 1 x i = ∑ i = 0 ∞ ∑ j = i ∞ f k − 1 , j 1 j + 1 x i \displaystyle F_k(x)=\sum_{i=0}^\infty f_{k,i}x^i=\sum_{i=0}^\infty \sum_{j=i}^nf_{k-1,j}\frac{1}{j+1}x^i=\sum_{i=0}^\infty \sum_{j=i}^\infty f_{k-1,j}\frac{1}{j+1}x^i Fk(x)=i=0fk,ixi=i=0j=infk1,jj+11xi=i=0j=ifk1,jj+11xi

= ∑ j = 0 ∞ f k − 1 , j 1 j + 1 ∑ i = 0 j x i = ∑ j = 0 ∞ f k − 1 , j 1 j + 1 x j + 1 − 1 x − 1 \displaystyle =\sum_{j=0}^\infty f_{k-1,j}\frac{1}{j+1}\sum_{i=0}^jx^i=\sum_{j=0}^\infty f_{k-1,j}\frac{1}{j+1}\frac{x^{j+1}-1}{x-1} =j=0fk1,jj+11i=0jxi=j=0fk1,jj+11x1xj+11

= 1 x − 1 ∑ j = 0 ∞ f k − 1 , j ∫ 1 x t j   d t = 1 x − 1 ∫ 1 x ( ∑ j = 0 ∞ f k − 1 , j t j )   d t \displaystyle =\frac{1}{x-1}\sum_{j=0}^\infty f_{k-1,j}\int_{1}^{x} t^j\,{\rm d}t=\frac{1}{x-1}\int_{1}^{x}(\sum_{j=0}^\infty f_{k-1,j} t^j)\,{\rm d}t =x11j=0fk1,j1xtjdt=x111x(j=0fk1,jtj)dt

= 1 x − 1 ∫ 1 x F k − 1 ( t )   d t \displaystyle =\frac{1}{x-1}\int_{1}^{x}F_{k-1}(t)\,{\rm d}t =x111xFk1(t)dt

积分下限为0的变限积分比较好处理,所以

F k ( x ) = 1 x − 1 ∫ 0 x − 1 F k − 1 ( t + 1 )   d t \displaystyle F_k(x)=\frac{1}{x-1}\int_{0}^{x-1}F_{k-1}(t+1)\,{\rm d}t Fk(x)=x110x1Fk1(t+1)dt

F k ( x + 1 ) = 1 x ∫ 0 x F k − 1 ( t + 1 )   d t \displaystyle F_k(x+1)=\frac{1}{x}\int_{0}^{x}F_{k-1}(t+1)\,{\rm d}t Fk(x+1)=x10xFk1(t+1)dt

G k ( x ) = F k ( x + 1 ) G_k(x)=F_k(x+1) Gk(x)=Fk(x+1),得

G k ( x ) = 1 x ∫ 0 x G k − 1 ( t )   d t \displaystyle G_k(x)=\frac{1}{x}\int_{0}^{x}G_{k-1}(t)\,{\rm d}t Gk(x)=x10xGk1(t)dt

两边展开,得

∑ i = 0 ∞ g k , i x i = ∑ i = 0 ∞ g k − 1 , i i + 1 x i \displaystyle \sum_{i=0}^\infty g_{k,i}x^i=\sum_{i=0}^\infty \frac{g_{k-1,i}}{i+1}x^i i=0gk,ixi=i=0i+1gk1,ixi

所以

g k , i = g k − 1 , i i + 1 \displaystyle g_{k,i}=\frac{g_{k-1,i}}{i+1} gk,i=i+1gk1,i

g m , i = g 0 , i ( i + 1 ) m \displaystyle g_{m,i}=\frac{g_{0,i}}{(i+1)^m} gm,i=(i+1)mg0,i

那么现在的问题是 { f k , n } \{f_{k,n}\} {fk,n} { g k , n } \{g_{k,n}\} {gk,n}之间怎么变换的。

先来看 { f k , n } \{f_{k,n}\} {fk,n}变换到 { g k , n } \{g_{k,n}\} {gk,n}

G k ( x ) = F k ( x + 1 ) G_k(x)=F_k(x+1) Gk(x)=Fk(x+1)

∑ i = 0 ∞ g k , i x i = ∑ i = 0 ∞ f k , i ( x + 1 ) i = ∑ i = 0 ∞ f k , i ∑ j = 0 i ( i j ) x j = ∑ i = 0 ∞ ( ∑ j = i ∞ ( j i ) f k , j ) x i \displaystyle \sum_{i=0}^\infty g_{k,i}x^i=\sum_{i=0}^\infty f_{k,i}(x+1)^i=\sum_{i=0}^\infty f_{k,i}\sum_{j=0}^i\dbinom{i}{j}x^j=\sum_{i=0}^\infty (\sum_{j=i}^\infty \dbinom{j}{i}f_{k,j})x_i i=0gk,ixi=i=0fk,i(x+1)i=i=0fk,ij=0i(ji)xj=i=0(j=i(ij)fk,j)xi

所以

g k , i = ∑ j = i ∞ ( j i ) f k , j = ∑ j = i ∞ j ! i ! ( j − i ) ! f k , j \displaystyle g_{k,i}=\sum_{j=i}^\infty \dbinom{j}{i}f_{k,j}=\sum_{j=i}^\infty \frac{j!}{i!(j-i)!}f_{k,j} gk,i=j=i(ij)fk,j=j=ii!(ji)!j!fk,j

i ! g k , i = ∑ j = i ∞ j ! ( j − i ) ! f k , j = ∑ j = i n j ! ( j − i ) ! f k , j \displaystyle i!g_{k,i}=\sum_{j=i}^\infty \frac{j!}{(j-i)!}f_{k,j}=\sum_{j=i}^n \frac{j!}{(j-i)!}f_{k,j} i!gk,i=j=i(ji)!j!fk,j=j=in(ji)!j!fk,j

r f k , n − j = j ! f k , j \displaystyle rf_{k,n-j}=j!f_{k,j} rfk,nj=j!fk,j,可得

i ! g k , i = ∑ j = i n r f k , n − j ( j − i ) ! = ∑ j + h = n − i r f k , h j ! \displaystyle i!g_{k,i}=\sum_{j=i}^n \frac{rf_{k,n-j}}{(j-i)!}=\sum_{j+h=n-i}\frac{rf_{k,h}}{j!} i!gk,i=j=in(ji)!rfk,nj=j+h=nij!rfk,h

显然右式是 { r f k , n } \{rf_{k,n}\} {rfk,n} { 1 n ! } \{\frac{1}{n!}\} {n!1}的卷积。

再来看 { g k , n } \{g_{k,n}\} {gk,n}变换到 { f k , n } \{f_{k,n}\} {fk,n}

g k , i = ∑ j = i ∞ ( j i ) f k , j \displaystyle g_{k,i}=\sum_{j=i}^\infty \dbinom{j}{i}f_{k,j} gk,i=j=i(ij)fk,j可二项式反演得

f k , i = ∑ j = i ∞ ( − 1 ) j − i ( j i ) g k , j \displaystyle f_{k,i}=\sum_{j=i}^\infty (-1)^{j-i}\dbinom{j}{i}g_{k,j} fk,i=j=i(1)ji(ij)gk,j

i ! f k , i = ∑ j = i n ( − 1 ) j − i j ! ( j − i ) ! g k , j \displaystyle i!f_{k,i}=\sum_{j=i}^n(-1)^{j-i}\frac{j!}{(j-i)!}g_{k,j} i!fk,i=j=in(1)ji(ji)!j!gk,j

r g k , n − j = j ! g k , j rg_{k,n-j}=j!g_{k,j} rgk,nj=j!gk,j,可得

i ! f k , i = ∑ j = i n ( − 1 ) j − i ( j − i ) ! r g k , n − j = ∑ j + h = n − i ( − 1 ) j j ! r g k , h \displaystyle i!f_{k,i}=\sum_{j=i}^n\frac{(-1)^{j-i}}{(j-i)!}rg_{k,n-j}=\sum_{j+h=n-i}\frac{(-1)^j}{j!}rg_{k,h} i!fk,i=j=in(ji)!(1)jirgk,nj=j+h=nij!(1)jrgk,h

右式为 { r g k , n } \{rg_{k,n}\} {rgk,n} { ( − 1 ) n n ! } \{\frac{(-1)^n}{n!}\} {n!(1)n}的卷积。

两遍 N T T NTT NTT即可。

复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<bitset>
#include<sstream>
#include<ctime>
//#include<chrono>
//#include<random>
//#include<unordered_map>
using namespace std;

#define ll long long
#define ls o<<1
#define rs o<<1|1
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
const double pi=acos(-1.0);
const double eps=1e-6;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int maxn=2e5+5;
ll read(){
	ll x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
namespace Ploynomial{  
    const ll mod=998244353,G=3;  
    int rev[maxn<<1];  
    ll qpow(ll a,ll p=mod-2){  
        ll res=1;  
        while(p){  
            if(p&1)res=res*a%mod;  
            a=a*a%mod;  
            p>>=1;  
        }  
        return res;  
    }  
    ll invG=qpow(G);  
    void print(ll *f,int n){  
        for(int i=0;i<n;i++)printf("%lld ",f[i]);  
        puts("");  
    }  
    void Rev(ll *f,int n){  
        for(int i=0;i<n;i++){  
            rev[i]=(rev[i>>1]>>1)|((i&1)?n>>1:0);  
            if(i<rev[i])swap(f[i],f[rev[i]]);  
        }  
    }  
    ll fix(ll x){  
        return (x%mod+mod)%mod;  
    }  
    void NTT(ll *f,int n,int flag){//1:DFT -1:IDFT  
        Rev(f,n);  
        for(int i=1;i<n;i<<=1){  
            ll wn=qpow(flag>0?G:invG,(mod-1)/(2*i));  
            for(int j=0;j<n;j+=2*i){  
                ll w=1;  
                for(int k=0;k<i;k++){  
                    ll tmp=w*f[j+k+i]%mod;  
                    f[j+k+i]=fix(f[j+k]-tmp);  
                    f[j+k]=fix(f[j+k]+tmp);  
                    w=w*wn%mod;  
                }  
            }  
        }  
        if(flag<0){  
            ll invn=qpow(n);  
            for(int i=0;i<n;i++)  
                f[i]=f[i]*invn%mod;  
        }  
    }  
    //加法卷积  
    ll f1[maxn<<1],g1[maxn<<1];  
    void Mul(ll *f,int n,ll *g,int m,ll *h){  
        int N;  
        for(N=1;N<n+m-1;N<<=1);  
        copy(f,f+n,f1);  
        fill(f1+n,f1+N,0);  
        copy(g,g+m,g1);  
        fill(g1+m,g1+N,0);  
        NTT(f1,N,1);  
        NTT(g1,N,1);  
        for(int i=0;i<N;i++)h[i]=f1[i]*g1[i]%mod;  
        NTT(h,N,-1);  
        fill(h+n+m-1,h+N,0);  
        fill(f1,f1+N,0);  
        fill(g1,g1+N,0);  
    }  
    //多项式求逆 g!=f  
    ll inv_t[maxn<<1];  
    void Inv(ll *f,int n,ll *g){  
        int N;  
        for(N=1;N<n;N<<=1);  
        fill(g,g+N,0);  
        g[0]=qpow(f[0]);  
        for(int i=2;i<=N;i<<=1){  
            copy(f,f+i,inv_t);  
            fill(inv_t+i,inv_t+(i<<1),0);  
            NTT(g,i<<1,1);  
            NTT(inv_t,i<<1,1);  
            for(int j=0;j<(i<<1);j++)  
                g[j]=fix(2*g[j]-g[j]*g[j]%mod*inv_t[j]%mod);  
            NTT(g,i<<1,-1);  
            fill(g+i,g+(i<<1),0);  
        }  
        fill(g+n,g+N,0);  
        fill(inv_t,inv_t+N,0);  
    }  
    //求导  
    int Deriv(ll *f,int n,ll *h){  
        for(int i=1;i<n;i++){  
            h[i-1]=f[i]*i%mod;  
        }  
        return n-1;  
    }  
    //积分  
    ll inv[maxn];  
    int Integ(ll *f,int n,ll *h){  
        inv[1]=1;  
        for(int i=2;i<=n;i++){  
            inv[i]=inv[mod%i]*(mod-mod/i)%mod;  
        }  
        for(int i=n;i>=1;i--){  
            h[i]=f[i-1]*inv[i]%mod;  
        }  
        h[0]=0;  
        return n+1;  
    }  
    //多项式开根 g!=f  
    ll sqrt_t[maxn<<1],sqrt_t2[maxn<<1];  
    void Sqrt(ll *f,int n,ll *g){  
        int N;  
        for(N=1;N<n;N<<=1);  
        fill(g,g+N,0);  
        g[0]=1;  
        ll inv2=qpow(2);  
        for(int i=2;i<=N;i<<=1){  
            Inv(g,i,sqrt_t);  
            NTT(sqrt_t,i<<1,1);  
            NTT(g,i<<1,1);  
            copy(f,f+i,sqrt_t2);  
            fill(sqrt_t2+i,sqrt_t2+(i<<1),0);  
            NTT(sqrt_t2,i<<1,1);  
            for(int j=0;j<(i<<1);j++){  
                g[j]=(g[j]*g[j]%mod+sqrt_t2[j])%mod*inv2%mod*sqrt_t[j]%mod;  
            }  
            NTT(g,i<<1,-1);  
            fill(g+i,g+(i<<1),0);  
        }  
        fill(g+n,g+N,0);  
    }  
    //多项式除法,已知f,g,deg(f)=n,deg(g)=m求q,r,deg(q)=n-m,deg(r)<m,满足f=g*q+r  
    void Reverse(ll *f,int n){  
        for(int i=0;i<n/2;i++)swap(f[i],f[n-1-i]);  
    }  
    ll div_t[maxn<<1];  
    void Div(ll *f,int n,ll *g,int m,ll *q,ll *r){  
        Reverse(f,n);  
        Reverse(g,m);  
        Inv(g,n-m+1,div_t);  
        Mul(f,n,div_t,n-m+1,q);  
        Reverse(q,n-m+1);  
        Reverse(g,m);  
        Reverse(f,n);  
        Mul(g,m,q,n-m+1,div_t);  
        for(int i=0;i<m-1;i++)r[i]=fix(f[i]-div_t[i]);  
    }  
      
    //多项式ln  
    ll ln_t[maxn<<1],ln_t2[maxn<<1];  
    void Ln(ll *f,int n,ll *h){  
        Inv(f,n,ln_t);  
        Deriv(f,n,ln_t2);  
        Mul(ln_t,n,ln_t2,n-1,h);  
        fill(h+n-1,h+2*n,0);  
        // for(int i=n-1;i<2*n-1;i++)h[i]=0;  
        Integ(h,n-1,h);  
        fill(ln_t,ln_t+n,0);  
        fill(ln_t2,ln_t2+n,0);  
    }  
  
    //多项式exp g!=f  保证f[0]=0
    ll exp_t[maxn<<1];  
    void Exp(ll *f,int n,ll *g){  
        int N;  
        for(N=1;N<n;N<<=1);  
        fill(g,g+N,0);  
        g[0]=1;  
        for(int i=2;i<=N;i<<=1){  
            Ln(g,i,exp_t);  
            for(int j=0;j<i;j++){  
                exp_t[j]=fix(f[j]-exp_t[j]);  
            }  
            exp_t[0]=(exp_t[0]+1)%mod;  
            Mul(exp_t,i,g,i,g);  
            fill(g+i,g+2*i,0);  
        }  
        fill(g+n,g+N,0);  
        fill(exp_t,exp_t+N,0);  
    }  
  
    //多项式快速幂,k可以很大,先用mod取模  
    ll pow_t[maxn<<1];  
    void Pow(ll *f,int n,ll k,ll *g){  
        Ln(f,n,pow_t);  
        for(int i=0;i<n;i++)pow_t[i]=pow_t[i]*k%mod;  
        Exp(pow_t,n,g);  
    }  
}  
#define Ploy Ploynomial

int n;
ll m;
ll f[maxn<<1],fac[maxn],rfac[maxn],g[maxn<<1],h[maxn<<1];
void init(int n){
	fac[0]=1;
	for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%Ploy::mod;
	rfac[n]=Ploy::qpow(fac[n]);
	for(int i=n-1;i>=0;i--){
		rfac[i]=rfac[i+1]*(i+1)%Ploy::mod;
	}
}
int main(void){
	// freopen("in.txt","r",stdin);
	scanf("%d%lld",&n,&m);
	init(n);
	for(int i=0;i<=n;i++){
		scanf("%lld",&f[n-i]);
		f[n-i]=f[n-i]*fac[i]%Ploy::mod;
	}
	Ploy::Mul(f,n+1,rfac,n+1,f);
	for(int i=0;i<=n;i++){
		g[n-i]=f[n-i]*Ploy::qpow(Ploy::qpow(i+1,m))%Ploy::mod;
	}
	int flag=1;
	for(int i=0;i<=n;i++){
		h[i]=flag*rfac[i]%Ploy::mod;
		flag=Ploy::mod-flag;
	}
	Ploy::Mul(g,n+1,h,n+1,g);
	for(int i=0;i<=n;i++){
		f[i]=g[n-i]*rfac[i]%Ploy::mod;
	}
	for(int i=0;i<=n;i++){
		printf("%lld ",f[i]);
	}
	puts("");
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值