2018.10.20【校内模拟】面包(数学期望)

传送门


解析:

神题啊。。

思路:

首先要进行转化,即方差等于平方的期望减去期望的平方。

这么说好像不太浅显啊。

方差的定义大概就是这样一个式子: s 2 = 1 n ∑ ( x i − x ˉ ) 2 s^2=\frac{1}{n}\sum(x_i-\bar{x})^2 s2=n1(xixˉ)2

然后我们将它化简一下 s 2 = 1 n ∑ ( x i 2 + x ˉ 2 − 2 x i x ˉ ) s^2=\frac{1}{n}\sum(x_i^2+\bar{x}^2-2 x_i\bar{x}) s2=n1(xi2+xˉ22xixˉ)
由于 x ˉ = 1 n ∑ x i \bar{x}=\frac{1}{n}\sum x_i xˉ=n1xi,所以上面的式子可以化简为 s 2 = ∑ x i 2 n − x ˉ 2 s^2=\frac{\sum x_i^2}{n}-\bar{x}^2 s2=nxi2xˉ2

那么我们要计算的就是 ∑ x i 2 \sum x_i^2 xi2 n n n,和 ∑ x i = n x ˉ \sum{x_i}=n\bar{x} xi=nxˉ

首先我们要计算 ∑ x \sum{x} x,就是每个矩阵把多少个点围住,换言之就是每个点被多少个矩阵围住。直接计算上下左右边界的组合方式就是我们要的 ∑ x \sum{x} x

然后考虑计算 ∑ x i 2 \sum{x_i^2} xi2,这个非常蛋疼,不过仍然有办法做,不理解的请感性理解一下。
就是直接枚举每个点对(包括自己与自己),计算将这个点对围住的有多少个矩形。可以用组合的思想来理解一下。

然后就是最蛋疼的地方了,计算 n n n,即,有多少个矩阵需要被统计在最后的答案当中。

枚举每一个点,统计以这个点为最左包含点的矩阵就可以了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline int getint(){
	re int num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return num;
}

cs ll mod=998244353;
inline ll quickpow(ll a,ll b,ll res=1){
	for(;b;b>>=1,a=a*a%mod)if(b&1)res=res*a%mod;
	return res;
}

inline ll inv(ll a){return quickpow(a,mod-2);}

cs int N=2005;
struct node{
	int x,y;
}a[N];

inline bool cmp(cs node &a,cs node &b){
	return a.x==b.x?a.y<b.y:a.x<b.x;
}

ll exex,ex,tot;
int n,m,k;
signed main(){
	n=getint();
	m=getint();
	k=getint();
	for(int re i=1;i<=k;++i)a[i].x=getint(),a[i].y=getint();
	for(int re i=1;i<=k;++i){
		exex=(exex+1ll*(n-a[i].x+1)*(a[i].x)%mod*(m-a[i].y+1)%mod*(a[i].y)%mod)%mod;
		for(int re j=1;j<=k;++j){
			int r=max(a[i].x,a[j].x);
			int l=min(a[i].x,a[j].x);
			int u=max(a[i].y,a[j].y);
			int d=min(a[i].y,a[j].y);
			ex=(ex+1ll*(n-r+1)*(l)%mod*(m-u+1)%mod*(d)%mod)%mod;
		}
	}
	a[++k]=(node){0,0};
	sort(a+1,a+k+1,cmp);
	for(int re i=1;i<=k;++i){
		int u=m,d=1;
		for(int re j=i-1;j;--j){
			if(u<d)break;
			if(a[j].x!=a[j+1].x)tot=(tot+1ll*(a[i].y-d+1)*(u-a[i].y+1)%mod*(n-a[i].x+1)%mod*(a[j+1].x-a[j].x)%mod)%mod;
			if(a[j].y>=a[i].y)u=min(u,a[j].y-1);
			if(a[j].y<=a[i].y)d=max(d,a[j].y+1);
		}
	}
	
	ll itot=inv(tot);
	exex=exex*itot%mod;
	exex=exex*exex%mod;
	ex=ex*itot%mod;
	
	cout<<(ex-exex+mod)%mod;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值