CF1042E Vasya and Magic Matrix 题解

题目传送门

题目大意: 给出一个矩阵,每个格子有一个数字,给出一个起点,每次可以往比自己数字小的格子跳,贡献为两点间欧几里得距离的平方,问期望贡献。

题解

先把所有格子按数字大小排,然后从小往大推,对于第 i i i 个格子,他可以到达前面所有比他小的格子,设最接近它且比他小的格子的位置为 k k k,那么有:
f [ i ] = 1 k ∑ j = 1 k f [ j ] + ( x i − x j ) 2 + ( y i − y j ) 2 f[i]=\frac 1 k \sum_{j=1}^k f[j]+(x_i-x_j)^2+(y_i-y_j)^2 f[i]=k1j=1kf[j]+(xixj)2+(yiyj)2

这种东西维护不了,按照套路把他拆开就能维护了:
f [ i ] = 1 k ∑ j = 1 k f [ j ] + x i 2 + x j 2 − 2 x i x j + y i 2 + y j 2 − 2 y i y j = x i 2 + y i 2 + ( 1 k ∑ j = 1 k x j 2 + y j 2 + f [ j ] ) − ( 2 x i k ∑ j = 1 k x j ) − ( 2 y i k ∑ j = 1 k y j ) \begin{aligned} f[i]&=\frac 1 k \sum_{j=1}^k f[j]+x_i^2+x_j^2-2x_ix_j+y_i^2+y_j^2-2y_iy_j\\ &=x_i^2+y_i^2+(\frac 1 k \sum_{j=1}^k x_j^2+y_j^2+f[j])-(\frac {2x_i} k\sum_{j=1}^k x_j)-(\frac {2y_i} k\sum_{j=1}^k y_j) \end{aligned} f[i]=k1j=1kf[j]+xi2+xj22xixj+yi2+yj22yiyj=xi2+yi2+(k1j=1kxj2+yj2+f[j])(k2xij=1kxj)(k2yij=1kyj)

统计一下前缀和就好。

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 1000010
#define mod 998244353

int n,m,X,Y,a[1010][1010];
int xj[maxn],yj[maxn],j2[maxn],f[maxn],sum_f[maxn];
struct node{int z,x,y;};
node b[maxn];
bool cmp(node x,node y){return x.z<y.z;}
int ksm(int x,int y)
{
	int re=1;
	while(y)
	{
		if(y&1)re=1ll*re*x%mod;
		x=1ll*x*x%mod;y>>=1;
	}
	return re;
}
#define inv(x) ksm(x,mod-2)

int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	scanf("%d",&a[i][j]),b[(i-1)*m+j]=(node){a[i][j],i,j};
	scanf("%d %d",&X,&Y);
	sort(b+1,b+n*m+1,cmp);
	int last=0;
	for(int i=1;i<=n*m;i++)
	{
		if(b[i].z>b[i-1].z)last=i-1;
		if(last)f[i]=((((1ll*b[i].x*b[i].x%mod+1ll*b[i].y*b[i].y%mod)%mod+1ll*j2[last]*inv(last)%mod)%mod
		-2ll*xj[last]*inv(last)%mod*b[i].x%mod+mod)%mod-2ll*yj[last]*inv(last)%mod*b[i].y%mod+mod)%mod;
		j2[i]=(j2[i-1]+((1ll*b[i].x*b[i].x%mod+1ll*b[i].y*b[i].y%mod)%mod+f[i])%mod)%mod;
		xj[i]=(xj[i-1]+b[i].x)%mod; yj[i]=(yj[i-1]+b[i].y)%mod;
		if(b[i].x==X&&b[i].y==Y)return printf("%d",f[i]),0;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值