[JZOJ6045]【NOI2019模拟2019.3.7】能量

Description

有n个随机变量xi,第i个在[li,ri]内均匀随机,问max((∑xi)^k,a ^k)的期望
n<=50,-2000<=li<=ri<=2000

Solution

先把li累加起来,每个xi变成在[0,len[i]]内均匀随机
F i ( x ) F_i(x) Fi(x)表示 ∑ j = 1 i x j \sum_{j=1}^{i}xj j=1ixj的概率密度函数
则有 F i ( x ) = ∫ x − l e n i x F i − 1 ( y ) d y F_i(x)=\int_{x-len_i}^xF_{i-1}(y)dy Fi(x)=xlenixFi1(y)dy
显然 F i ( x ) F_i(x) Fi(x)是一个分段函数,考虑维护每一段
为了方便我们可以直接设[i,i+1]为一段
然后根据积分的意义这一个东西是可以直接求的
考虑求答案只需要算 ∫ l r F n ( x ) x k d x \int _l^rF_n(x)x^kdx lrFn(x)xkdx这个也可以直接算
就是有点难写

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

typedef long long ll;
typedef vector<int> poly;

const int N=55,M=2e5+5,Mo=998244353;

int pwr(int x,int y) {
	int z=1;
	for(;y;y>>=1,x=(ll)x*x%Mo)
		if (y&1) z=(ll)z*x%Mo;
	return z;
}

void inc(int &x,int y) {x=x+y>=Mo?x+y-Mo:x+y;}
void dec(int &x,int y) {x=x-y<0?x-y+Mo:x-y;}

int Abs(int x) {return x<0?-x:x;}

int n,K,a,s,l,r,ct,sum[M],R,inv[N],It[M],pw[N],C[N][N];
poly p[M],q[M],pl;

int Integral (poly a) {
	int ans=0;
	for(int i=0;i<a.size();i++) inc(ans,(ll)inv[i+1]*a[i]%Mo);
	return ans;
}

void trans(int len) {
	fo(i,R,R+len-1) p[i].resize(0);R+=len;
	fo(i,0,R-1) It[i]=Integral(p[i]);
	sum[0]=It[0];fo(i,1,R-1) sum[i]=(sum[i-1]+It[i])%Mo;
	fo(i,0,R-1) {
		int j=i-len;
		q[i].resize(p[i].size()+1);q[i][0]=0;
		for(int k=1;k<q[i].size();k++) q[i][k]=(ll)p[i][k-1]*inv[k]%Mo;
		if (i>0) inc(q[i][0],sum[i-1]);
		if (j>=0) {
			if (j>0) dec(q[i][0],sum[j-1]);
			pl.resize(p[j].size()+1);pl[0]=0;
			for(int k=0;k<p[j].size();k++) pl[k+1]=(ll)p[j][k]*inv[k+1]%Mo;
			while (q[i].size()<pl.size()) q[i].push_back(0);
			for(int k=1;k<pl.size();k++) dec(q[i][k],pl[k]);
		}
	}
	int inv=pwr(len,Mo-2);
	fo(i,0,R-1) {
		p[i].resize(q[i].size());
		for(int j=0;j<p[i].size();j++) p[i][j]=(ll)q[i][j]*inv%Mo;
	}
}

int len[N];

int main() {
	freopen("power.in","r",stdin);
	freopen("power.out","w",stdout);
	scanf("%d%d%d",&n,&K,&a);bool fir=0;int sl=0;
	inv[0]=inv[1]=1;fo(i,2,n) inv[i]=(ll)(Mo-Mo/i)*inv[Mo%i]%Mo;
	fo(i,1,n) {
		scanf("%d%d",&l,&r);
		len[i]=r-l;sl+=l;
	}
	sort(len+1,len+n+1);
	fo(i,1,n) {
		if (!len[i]) continue;
		if (!fir) {
			int iv=pwr(len[i],Mo-2);
			fo(j,0,len[i]-1) p[j].resize(1),p[j][0]=iv;
			R=len[i];fir=1;
		} else trans(len[i]);
	}
	if (!fir) {
		if (K&1) printf("%d\n",(sl>=a)?pwr(sl,K):pwr(a,K));
		else printf("%d\n",(Abs(sl)>=Abs(a))?pwr(sl,K):pwr(a,K));
		return 0;
	}
	fo(i,0,n) {
		C[i][0]=1;
		fo(j,1,i) C[i][j]=(C[i-1][j]+C[i-1][j-1])%Mo;
	}
	if (K&1) {
		int ans=0;
		fo(i,0,R-1) 
			if (i+sl>=a) {
				pl.clear();pl.resize(p[i].size());int id=((i+sl)+Mo)%Mo;
				pw[0]=1;for(int j=1;j<p[i].size();j++) pw[j]=(ll)pw[j-1]*id%Mo;
				for(int k=0;k<p[i].size();k++)
					fo(j,0,k) {
						int now=(ll)p[i][k]*C[k][j]%Mo*pw[k-j]%Mo;
						if ((k-j)&1) dec(pl[j],now);
						else inc(pl[j],now);
					}
				for(int k=0;k<pl.size();k++) {
					int ret=(pwr(id+1,k+K+1)-pwr(id,k+K+1)+Mo)%Mo;
					inc(ans,(ll)pl[k]*pwr(k+K+1,Mo-2)%Mo*ret%Mo);
				}
			} else inc(ans,(ll)Integral(p[i])*pwr(a,K)%Mo);
		printf("%d\n",ans);
	} else {
		int ans=0;
		fo(i,0,R-1) 
			if (Abs(i+sl)>=Abs(a)&&Abs(i+sl+1)>=Abs(a)) {
				pl.clear();pl.resize(p[i].size());
				pw[0]=1;for(int j=1;j<p[i].size();j++) pw[j]=(ll)pw[j-1]*(i+sl)%Mo;
				for(int k=0;k<p[i].size();k++)
					fo(j,0,k) {
						int now=(ll)p[i][k]*C[k][j]%Mo*pw[k-j]%Mo;
						if ((k-j)&1) dec(pl[j],now);
						else inc(pl[j],now);
					}
				for(int k=0;k<pl.size();k++) {
					int ret=(pwr(i+sl+1,k+K+1)-pwr(i+sl,k+K+1)+Mo)%Mo;
					inc(ans,(ll)pl[k]*pwr(k+K+1,Mo-2)%Mo*ret%Mo);
				}
			} else inc(ans,(ll)Integral(p[i])*pwr(a,K)%Mo);
		printf("%d\n",ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值