• 「PMOI-2」简单构造题


    定义一个长度为(n)的序列(A)的权值为:

    [sum_{l=1}^nsum_{r=l}^n f_A(l,r) ]

    其中(f_A(l,r)f)就是在(A)的区间([l,r])中,「所有在该区间内出现过的元素出现次数的乘积」再乘上「区间内所有元素的乘积」。

    要求构造一个长为(n)的序列,其中每个元素都是([1,m])中的整数,最大化其权值。

    她并不会,只好均匀随机(n)([1,m])中的整数组成一个数列,然后输出其权值。

    当然,她的这份程序一分都没拿到;但她想知道,生成出的序列期望权值是多少。

    为了防止精度问题,答案需要对(998244353)取模。


    想到第一步之后就是做烂的套路了...

    可以统计每种长度的所有区间的贡献。设(g_n)为所有长度为(i)的区间的贡献,那么答案就是:

    [Ans=sum_{i=1}^ng_i(n-i+1)m^{n-i} ]

    由于数的位置不同数列就不同,我们可以写出选每种数的(EGF)

    [F(x)=sum_{n=0}frac{nx^n}{n!}=sum_{n=0}frac{x^n}{(n-1)!} ]

    那么(g)(EGF)就可以表示成:

    [G(x)=prod_{i=1}^{m}F(ix)=exp(sum_{i=1}^nln F(ix)) ]

    那么求出(ln F(x))的系数之后,第(n)次项系数乘上(sum_{i=1}^mi^n)就是(sum ln F(ix))(n)次项系数。

    现在就是做烂了的自然数幂和。写出这个东西的(EGF)

    [H(x)=sum_{n=0}(sum_{i=0}^mi^n)frac{x^n}{n!} =sum_{i=0}^msum_{n=0}frac{(ix)^n}{n!} =sum_{i=0}^me^{ix}=frac{e^{(m+1)x}-1}{e^x-1} ]

    这里为了方便让(i)(0)开始的,最后求出系数后让(0)次项为(0)即可。但是这里分母的(0)次项为(0),怎么求逆呢?注意到分子的(0)次项也是(0),所以同时给分子分母都除个(x)即可。总复杂度(mathcal{O}(nlog n))

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define cn const
    #define fp(i,a,b) for(rg int i=(a),ed=(b);i<=ed;++i)
    #define fb(i,a,b) for(rg int i=(a),ed=(b);i>=ed;--i)
    using namespace std;
    typedef cn int cint;
    cint maxn = 200010, mod = 998244353, g = 3, invg = (mod+1)/3;
    int n, m, fac[maxn] = {1}, ifac[maxn], inv[maxn] = {0, 1};
    int F[maxn] = {1}, ln[maxn<<2], G[maxn<<2], ans;
    int A[maxn<<2], B[maxn<<2], H[maxn<<2], pw = 1;
    int lim, hst, rev[maxn<<2];
    il int fpow(int a, int b, int ans = 1){
    	for(; b; b >>= 1, a = 1ll*a*a%mod)if(b&1)ans = 1ll*ans*a%mod;
    	return ans;
    }
    il void init(int n){
    	lim = 1, hst = 0;
    	while(lim < n)lim <<= 1, ++hst;
    	fp(i, 1, lim-1)rev[i] = (rev[i>>1]>>1)|((i&1)<<hst-1);
    }
    il void ntt(int *a, cint &typ){
    	fp(i, 1, lim-1)if(i > rev[i])swap(a[i], a[rev[i]]);
    	for(rg int md = 1; md < lim; md <<= 1){
    		rg int len = md<<1, Gn = fpow(typ ? invg : g, (mod-1)/len);
    		for(rg int l = 0; l < lim; l += len){
    			for(rg int nw = 0, Pow = 1; nw < md; ++nw, Pow = 1ll*Pow*Gn%mod){
    				rg int x = a[l+nw], y = 1ll*Pow*a[l+nw+md]%mod;
    				a[l+nw] = (x+y)%mod, a[l+nw+md] = (x-y+mod)%mod;
    			}
    		}
    	}
    	if(!typ)return;
    	rg int inv = fpow(lim, mod-2);
    	fp(i, 0, lim-1)a[i] = 1ll*a[i]*inv%mod;
    }
    int inv_ary[maxn<<2];
    void get_inv(int *a, int *f, int n){
    	if(n == 1)return f[0] = fpow(a[0], mod-2), void();
    	get_inv(a, f, n+1>>1), init(n*2-1);
    	fp(i, 0, n-1)inv_ary[i] = a[i];
    	ntt(f, 0), ntt(inv_ary, 0);
    	fp(i, 0, lim-1)f[i] = 1ll*f[i]*(2-1ll*f[i]*inv_ary[i]%mod+mod)%mod;
    	ntt(f, 1);
    	fp(i, n, lim-1)f[i] = 0;
    	fp(i, 0, lim-1)inv_ary[i] = 0;
    }
    int ln_ary[maxn<<2];
    il void get_ln(int *a, int *f, int n){
    	get_inv(a, ln_ary, n), init(n*2-1);
    	fp(i, 1, n-1)f[i-1] = 1ll*a[i]*i%mod;
    	ntt(f, 0), ntt(ln_ary, 0);
    	fp(i, 0, lim-1)f[i] = 1ll*f[i]*ln_ary[i]%mod;
    	ntt(f, 1);
    	fb(i, n-1, 1)f[i] = 1ll*f[i-1]*inv[i]%mod;
    	fp(i, n, lim-1)f[i] = 0;
    	fp(i, 0, lim-1)ln_ary[i] = 0;
    	f[0] = 0;
    }
    int exp_ary[maxn<<2];
    void get_exp(int *a, int *f, int n){
    	if(n == 1)return f[0] = 1, void();
    	get_exp(a, f, n+1>>1), get_ln(f, exp_ary, n), init(n*2-1);
    	fp(i, 0, n-1)exp_ary[i] = (a[i]-exp_ary[i]+mod)%mod;
    	if((++exp_ary[0]) == mod)exp_ary[0] = 0;
    	ntt(f, 0), ntt(exp_ary, 0);
    	fp(i, 0, lim-1)f[i] = 1ll*f[i]*exp_ary[i]%mod;
    	ntt(f, 1);
    	fp(i, n, lim-1)f[i] = 0;
    	fp(i, 0, lim-1)exp_ary[i] = 0;
    }
    int main(){
    	cin >> n >> m;
    	fp(i, 1, n+1)fac[i] = 1ll*fac[i-1]*i%mod;
    	ifac[n+1] = fpow(fac[n+1], mod-2);
    	fb(i, n+1, 1)ifac[i-1] = 1ll*ifac[i]*i%mod;
    	fp(i, 2, n+1)inv[i] = mod-1ll*(mod/i)*inv[mod%i]%mod;
    	
    	fp(i, 1, n)F[i] = ifac[i-1];
    	get_ln(F, ln, n+1);
    	fp(i, 0, n)pw = 1ll*pw*(m+1)%mod, A[i] = 1ll*pw*ifac[i+1]%mod, B[i] = ifac[i+1];
    	get_inv(B, H, n+1), init(n*2+1), ntt(H, 0), ntt(A, 0);
    	fp(i, 0, lim-1)H[i] = 1ll*H[i]*A[i]%mod;
    	ntt(H, 1), H[0] = m;
    	fp(i, 1,n)H[i] = 1ll*H[i]*fac[i]%mod;
    	fp(i, 0, n)ln[i] = 1ll*ln[i]*H[i]%mod;
    	get_exp(ln, G, n+1);
    	fp(i, 0, n)G[i] = 1ll*G[i]*fac[i]%mod;
    	
    	pw = 1;
    	fp(i, 1, n)ans = (ans+1ll*i*pw%mod*G[n-i+1])%mod, pw = 1ll*pw*m%mod;
    	printf("%lld
    ", 1ll*ans*fpow(fpow(m, n), mod-2)%mod);
    	return 0;
    }
    
  • 相关阅读:
    时间计算
    DateTime
    C# trim split dataGrid
    something
    生活
    如何导入外部的源码到eclipse中
    java类中获取ServletContext的方法
    获取spring容器上下文(webApplicationContext)的几种方法
    java反射(转)
    mysql常见命令
  • 原文地址:https://www.cnblogs.com/akura/p/14502349.html
Copyright © 2020-2023  润新知