本文主要是介绍牛客国庆集训派对Day4-E-乒乓球(NTT),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
链接:https://www.nowcoder.com/acm/contest/204/E
来源:牛客网
题目描述
小 Bo 是某省乒乓球名列前茅的选手,现在他有 n 颗乒乓球一字排开,第 i 颗乒乓球的权值为 wi
每次他会随机从现有的乒乓球中等概率选一颗拿走,然后得到的收益是这颗球左边第一个乒乓球和右边第一个乒乓球的权值的乘积,如果左边没有乒乓球或者右边没有乒乓球,则收益为 0,这个过程会重复进行到所有球都被拿走为止
现在小 Bo 想知道他的期望总收益
为了方便,你只需要输出答案对 998244353 取模的值
输入描述:
第一行一个正整数 n 第二行 n 个正整数 w1…wn
输出描述:
输出答案对 998244353 取模的值
示例1
输入
复制
3 1 1 1
输出
复制
332748118
说明
答案是
备注:
1≤ n≤ 105 1≤ wi≤ 107
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define mod 998244353
ll a[300005],b[300005],n,ans;
ll wn[30];
ll q(ll x,ll y)
{ll res=1;x%=mod;while(y){if(y%2)res=res*x%mod;x=x*x%mod;y/=2;}return res;
}
void getwn()
{for(int i=0;i<20;i++){int tmp=1<<i;wn[i]=q(3ll,(mod-1)/tmp);}
}
void change(ll y[],int len)
{int i,j,k;for(i=1,j=len/2;i<len-1;i++){if(i<j) swap(y[i],y[j]);k=len/2;while(j>=k)j-=k,k/=2;if(j<k)j+=k; }
}
void ntt(ll y[], int len, int on)
{change(y, len); int id=0;for(int h=2;h<=len;h<<=1){id++;for(int j=0;j<len;j+=h){ll w=1;for(int k=j;k<j+h/2;k++){ll u=y[k];ll t=w*y[k+h/2]%mod;y[k]=(u+t)%mod;y[k+h/2]=(u-t+mod)%mod;w=w*wn[id]%mod;}}}if(on==-1){ll inv=q(len,mod-2);for(int i=1;i<len/2;i++)swap(y[i],y[len-i]);for(int i=0;i<len;i++)y[i]=y[i]*inv%mod;}
}
int main(void)
{getwn();scanf("%lld",&n);for(int i=0;i<n;i++)scanf("%lld",&a[i]);for(int i=0;i<n;i++)b[n-i-1]=a[i];int len=1;while(len<=n*2) len*=2;ntt(a,len,1);ntt(b,len,1);for(int i=0;i<len;i++)a[i]=a[i]*b[i]%mod;ntt(a,len,-1);for(int i=2;i<n;i++)ans=(ans+2ll*a[n+i-1]*q((ll)i*(i+1),mod-2)%mod)%mod;printf("%lld\n",ans);return 0;
}
这篇关于牛客国庆集训派对Day4-E-乒乓球(NTT)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!