链接:
来源:牛客网
小 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("%lldn",ans);return 0;
}
本文发布于:2024-01-28 14:19:21,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17064227678028.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |