ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【题解】2020ICPC澳门 A.Accelerator

2021-10-07 19:01:56  阅读:284  来源: 互联网

标签:return Accelerator int 题解 sum poly 2020ICPC prod mod


题意

给定一个长为\(n\)的序列\(\{a_i\}\),等概率随机一个长为\(n\)的排列\(\{p_i\}\),求\(\{a_{p_i}\}\)的后缀积的和的期望。

\(1\le n\le 10^5,1\le a_i\le 10^9\)

题解

答案即为

\[\frac{1}{n!}\sum_{p}\sum_{i=1}^{n}\prod_{j\ge i}a_{p_{j}}. \]

我们考虑一个长为\(k\)的项\(\prod_{j=1}^{k}a_{q_{j}}\)会在分子中出现多少次,相当于序列的后\(k\)个数随机排列,前\(n-k\)个数随机排列的方案数,故出现次数为\(k!(n-k)!\)。记\(S=\{1,2,3,...,n\}\),则答案可以改写成

\[\frac{1}{n!}\sum_{p}\sum_{i=1}^{n}\prod_{j\ge i}a_{p_{j}}=\frac{1}{n!}\sum_{k=1}^{n}k!(n-k)!\sum_{T\subset S,|T|=k}\prod_{i\in T}a_i=\sum_{k=1}^{n}\frac{k!(n-k)!}{n!}\sum_{T\subset S,|T|=k}\prod_{i\in T}a_i=\sum_{k=1}^n\frac{\sum_{T\subset S,|T|=k}\prod_{i\in T}a_i}{\binom{n}{k}}, \]

\[\sum_{T\subset S,|T|=k}\prod_{i\in T}a_i=[x^k]\prod_{i=1}^{n}(1+a_i x), \]

于是分治计算\(\prod_{i=1}^n(1+a_i x)\)即可。复杂度\(O(n\log^2n )\)

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int mod=998244353;
const int N=100005;
const double pi=acos(-1.0);
inline int add(int x,int y){x+=y;return x>=mod?x-mod:x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
int pm(int x,int y){
    int res=1;
    while(y){
        if(y&1) res=mul(res,x);
        x=mul(x,x),y>>=1;
    }
    return res;
}
inline int getinv(int x){return pm(x,mod-2);}
inline int getN(int x){
    int N=1;
    while(N<=x) N<<=1;
    return N;
}
const int maxn=1<<18;
namespace Poly{
    int inv[maxn];
    void init(int N){
        inv[0]=inv[1]=1;
        for(int i=2;i<N;i++) inv[i]=mul(inv[mod%i],mod-mod/i);
    }
    void ntt(int *A,int N,int opt){
        for(int i=0,j=0;i<N;i++){
            if(i<j) swap(A[i],A[j]);
            for(int l=(N>>1);(j^=l)<l;l>>=1);
        }
        for(int l=2;l<=N;l<<=1){
            int m=(l>>1),w0=pm(3,(mod-1)/l);
            if(opt==-1) w0=getinv(w0);
            for(int j=0;j<N;j+=l)
                for(int i=j,w=1;i<j+m;i++,w=mul(w,w0)){
                    int v=mul(A[i+m],w);
                    A[i+m]=add(A[i],mod-v);
                    A[i]=add(A[i],v);
                }
        }
        if(opt==-1){
            int tmp=getinv(N);
            for(int i=0;i<N;i++) A[i]=mul(A[i],tmp);
        }
    }
}
using Poly::ntt;
using poly=vector<int>;
int A[maxn],B[maxn],C[maxn];
poly polymul(poly a,poly b){
    poly c;
    int n=a.size()-1,m=b.size()-1;
    c.resize(n+m+1);
    int N=getN(n+m);
    for(int i=0;i<=n;i++) A[i]=a[i];
    for(int i=n+1;i<N;i++) A[i]=0;
    for(int i=0;i<=m;i++) B[i]=b[i];
    for(int i=m+1;i<N;i++) B[i]=0;
    ntt(A,N,1),ntt(B,N,1);
    for(int i=0;i<N;i++) A[i]=mul(A[i],B[i]);
    ntt(A,N,-1);
    for(int i=0;i<=n+m;i++) c[i]=A[i];
    return c;
}
int n,b[N];
poly sol(int l,int r){
	if(l==r){return poly{1,b[l]};}
	int mid=l+r>>1;
	return polymul(sol(l,mid),sol(mid+1,r));
}
ll ss[N],invs[N];
ll binom(int n,int m){return ss[n]*invs[m]%mod*invs[n-m]%mod;}
void f1(){
	ss[0]=1;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		ss[i]=ss[i-1]*i%mod;
		scanf("%d",&b[i]);
	}
	invs[n]=pm(ss[n],mod-2);
	for(int i=n-1;i>=0;i--)invs[i]=invs[i+1]*(i+1)%mod;
	poly res=sol(1,n);
	ll ans=0;
	for(int i=1;i<=n;i++){
		ans=(ans+1ll*res[i]*getinv(binom(n,i))%mod)%mod;
	}
	printf("%lld\n",ans);
	
}
int main(){
	int t;scanf("%d",&t);
	while(t--)
		f1();
	return 0;	
}

标签:return,Accelerator,int,题解,sum,poly,2020ICPC,prod,mod
来源: https://www.cnblogs.com/bobh/p/15376724.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有