感觉不会期望。

首先把所有格子按照权值从小到大排一下序,这样一共有$n * m$个元素,每个元素有三个属性$x, y, val$。

下文中的下标均为排序后的下标。

这样子我们就可以推出公式:

    $f_i = \frac{1}{k}\sum_{j = 1}^{k}(f_j + (x_j - x_i)^2 + (y_j - y_i)^2)$    $($保证$val_j < val_i$并且这样的元素一共有$k$个$)$。

暴力转移是$n^2$的,但是我们可以把这个式子拆开:

    $f_i = \frac{1}{k}\sum_{j = 1}^{k}f_j + x_i^2 + y_i^2 + \frac{1}{k}\sum_{j = 1}^{k}x_j^2 + \frac{1}{k}\sum_{j = 1}^{k}y_j^2 - \frac{2x_i}{k}\sum_{j = 1}^{k}x_j - \frac{2y_i}{k}\sum_{j = 1}^{k}y_j$

维护$\sum_{i = 1}^{k}x_i^2$、$\sum_{i = 1}^{k}y_i^2$、$\sum_{i = 1}^{k}y_i$、$\sum_{i = 1}^{k}x_i$、$\sum_{i = 1}^{k}f_i$五个前缀和就可以$O(n)$转移了。

要注意$val_i$可能为$0$。

加上算逆元的时间一共是$O(nmlogP)$。

Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll; const int N = ;
const int M = 1e6 + ;
const ll P = 998244353LL; int n, m, tot = ;
ll a[N][N], f[M]; struct Item {
ll x, y, val;
} b[M]; bool cmp(const Item &u, const Item &v) {
return u.val < v.val;
} inline ll fpow(ll x, ll y) {
ll res = 1LL;
for(; y > ; y >>= ) {
if(y & ) res = res * x % P;
x = x * x % P;
}
return res;
} inline void up(ll &x, ll y) {
x = ((x + y) % P + P) % P;
} template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} int main() {
read(n), read(m);
for(int i = ; i <= n; i++)
for(int j = ; j <= m; j++) {
read(a[i][j]);
b[++tot].x = 1LL * i, b[tot].y = 1LL * j, b[tot].val = a[i][j];
} int stx, sty, pos; read(stx), read(sty);
sort(b + , b + + tot, cmp);
for(int i = ; i <= tot; i++)
if(b[i].x == stx && b[i].y == sty) {
pos = i;
break;
} ll sumx = 0LL, sumy = 0LL, sumx2 = 0LL, sumy2 = 0LL, sumf = 0LL; int k = ;
for(int i = ; i <= pos; i++) {
for(; b[k].val < b[i].val && k <= pos; k++) {
up(sumx, b[k].x), up(sumy, b[k].y);
up(sumx2, b[k].x * b[k].x % P), up(sumy2, b[k].y * b[k].y % P);
up(sumf, f[k]);
}
if(k <= ) continue;
ll invK = fpow(k - , P - );
up(f[i], invK * sumf % P);
up(f[i], b[i].x * b[i].x % P), up(f[i], b[i].y * b[i].y % P);
up(f[i], invK * sumx2 % P), up(f[i], invK * sumy2 % P);
up(f[i], -2LL * b[i].x % P * invK % P * sumx % P), up(f[i], -2LL * b[i].y % P * invK % P * sumy % P);
} printf("%lld\n", f[pos]);
return ;
}

提醒自己:写快速幂不要把函数名写成$pow$,因为这样WA了很多次。

CF1042E Vasya and Magic Matrix的更多相关文章

  1. CF1042E Vasya and Magic Matrix 题解

    题目链接 思路分析 看到题目中 \(n,m \leq 1000\) ,故直接考虑 \(O(n^2)\) 级别做法. 我们先把所有的点按照 \(val\) 值从小到大排序,这样的话二维问题变成序列问题. ...

  2. CF 1042 E. Vasya and Magic Matrix

    E. Vasya and Magic Matrix http://codeforces.com/contest/1042/problem/E 题意: 一个n*m的矩阵,每个位置有一个元素,给定一个起点 ...

  3. Vasya and Magic Matrix CodeForces - 1042E (概率dp)

    大意:给定n*m矩阵, 初始位置(r,c), 每一步随机移动到权值小于当前点的位置, 得分为移动距离的平方, 求得分期望. 直接暴力dp的话复杂度是O(n^4), 把距离平方拆开化简一下, 可以O(n ...

  4. Educational Codeforces Round 9 F. Magic Matrix 最小生成树

    F. Magic Matrix 题目连接: http://www.codeforces.com/contest/632/problem/F Description You're given a mat ...

  5. Educational Codeforces Round 48 (Rated for Div. 2) D 1016D Vasya And The Matrix (构造)

    D. Vasya And The Matrix time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  6. codeforces1016 D. Vasya And The Matrix(思维+神奇构造)

    D. Vasya And The Matrix time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  7. Codeforces 632F Magic Matrix(bitset)

    题目链接  Magic Matrix 考虑第三个条件,如果不符合的话说明$a[i][k] < a[i][j]$ 或 $a[j][k] < a[i][j]$ 于是我们把所有的$(a[i][j ...

  8. D. Vasya And The Matrix(Educational Codeforces Round 48)

    D. Vasya And The Matrix time limit per test2 seconds memory limit per test256 megabytes inputstandar ...

  9. Vasya And The Matrix CodeForces - 1016D (思维+构造)

    Now Vasya is taking an exam in mathematics. In order to get a good mark, Vasya needs to guess the ma ...

随机推荐

  1. shiro2

    mapper接口:根据用户id查询用户权限的菜单 service接口:根据用户id查询用户权限的菜单 获取用户权限范围的url 思路: 在用户认证时,认证通过,根据用户id从数据库获取用户权限范围的u ...

  2. oracle 序列 + 触发器 实现 ID自动增长

    1.创建序列 create sequence emp_sequence increment by ----每次增加几个 minvalue ----最小值为1 nomaxvalue----不限制最大值 ...

  3. delphi各个版本编译开关值

    delphi各个版本编译开关值 {$IFDEF VER80}  - Delphi 1{$IFDEF VER90}  - Delphi 2{$IFDEF VER100} - Delphi 3{$IFDE ...

  4. LINQ 学习路程 -- 查询操作 Join

    Join操作是将两个集合联合 Joining Operators Usage Join 将两个序列连接并返回结果集 GroupJoin 根据key将两个序列连接返回,像是SQL中的Left Join ...

  5. python中字符串使用需要注意的地方

    1. r''的使用 'r'是防止字符转义的 如果路径中出现'\t'的话 不加r的话\t就会被转义 而加了'r'之后'\t'就能保留原有的样子 2. u''的使用 引号之前加上字母u时,python会将 ...

  6. matlab画圆

    MATLAB rectangle函数1 语法说明rectangle('Position', pos)rectangle('Position', pos, 'Curvature', cur)rectan ...

  7. Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析

    Office文件的奥秘——.NET平台下不借助Office实现Word.Powerpoint等文件的解析 分类: 技术 2013-07-26 15:38 852人阅读 评论(0) 收藏 举报 Offi ...

  8. 超链接向servlet传参数

    超链接传参数方式如下: <a href=xxxServlet?flag=1  target=“XX”></a> 注意:target=“XX”是用来指定在什么窗体打开.xx为该窗 ...

  9. Java读取文件的时候,如何让指针重新回到文件的开头

    今天在测试IO流的使用的时候发现在reader读取文件之后,再向文件添加内容,再继续读文件,打印出的结果只能读取追加的文件. 如何才能重新读取呢?试了mark和reset,似乎会报异常.记在这以后看是 ...

  10. Java中常见的集合框架

    1. 一.collection (有序)接口的实现的接口 set  list 其中set接口的实现类是HashSet,List接口的实现类是ArrayList.LinkList.Vector 二.Ma ...