CF1042E Vasya and Magic Matrix
感觉不会期望。
首先把所有格子按照权值从小到大排一下序,这样一共有$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的更多相关文章
- CF1042E Vasya and Magic Matrix 题解
题目链接 思路分析 看到题目中 \(n,m \leq 1000\) ,故直接考虑 \(O(n^2)\) 级别做法. 我们先把所有的点按照 \(val\) 值从小到大排序,这样的话二维问题变成序列问题. ...
- CF 1042 E. Vasya and Magic Matrix
E. Vasya and Magic Matrix http://codeforces.com/contest/1042/problem/E 题意: 一个n*m的矩阵,每个位置有一个元素,给定一个起点 ...
- Vasya and Magic Matrix CodeForces - 1042E (概率dp)
大意:给定n*m矩阵, 初始位置(r,c), 每一步随机移动到权值小于当前点的位置, 得分为移动距离的平方, 求得分期望. 直接暴力dp的话复杂度是O(n^4), 把距离平方拆开化简一下, 可以O(n ...
- Educational Codeforces Round 9 F. Magic Matrix 最小生成树
F. Magic Matrix 题目连接: http://www.codeforces.com/contest/632/problem/F Description You're given a mat ...
- 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 ...
- 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 ...
- Codeforces 632F Magic Matrix(bitset)
题目链接 Magic Matrix 考虑第三个条件,如果不符合的话说明$a[i][k] < a[i][j]$ 或 $a[j][k] < a[i][j]$ 于是我们把所有的$(a[i][j ...
- 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 ...
- 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 ...
随机推荐
- shiro2
mapper接口:根据用户id查询用户权限的菜单 service接口:根据用户id查询用户权限的菜单 获取用户权限范围的url 思路: 在用户认证时,认证通过,根据用户id从数据库获取用户权限范围的u ...
- oracle 序列 + 触发器 实现 ID自动增长
1.创建序列 create sequence emp_sequence increment by ----每次增加几个 minvalue ----最小值为1 nomaxvalue----不限制最大值 ...
- delphi各个版本编译开关值
delphi各个版本编译开关值 {$IFDEF VER80} - Delphi 1{$IFDEF VER90} - Delphi 2{$IFDEF VER100} - Delphi 3{$IFDE ...
- LINQ 学习路程 -- 查询操作 Join
Join操作是将两个集合联合 Joining Operators Usage Join 将两个序列连接并返回结果集 GroupJoin 根据key将两个序列连接返回,像是SQL中的Left Join ...
- python中字符串使用需要注意的地方
1. r''的使用 'r'是防止字符转义的 如果路径中出现'\t'的话 不加r的话\t就会被转义 而加了'r'之后'\t'就能保留原有的样子 2. u''的使用 引号之前加上字母u时,python会将 ...
- matlab画圆
MATLAB rectangle函数1 语法说明rectangle('Position', pos)rectangle('Position', pos, 'Curvature', cur)rectan ...
- Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析
Office文件的奥秘——.NET平台下不借助Office实现Word.Powerpoint等文件的解析 分类: 技术 2013-07-26 15:38 852人阅读 评论(0) 收藏 举报 Offi ...
- 超链接向servlet传参数
超链接传参数方式如下: <a href=xxxServlet?flag=1 target=“XX”></a> 注意:target=“XX”是用来指定在什么窗体打开.xx为该窗 ...
- Java读取文件的时候,如何让指针重新回到文件的开头
今天在测试IO流的使用的时候发现在reader读取文件之后,再向文件添加内容,再继续读文件,打印出的结果只能读取追加的文件. 如何才能重新读取呢?试了mark和reset,似乎会报异常.记在这以后看是 ...
- Java中常见的集合框架
1. 一.collection (有序)接口的实现的接口 set list 其中set接口的实现类是HashSet,List接口的实现类是ArrayList.LinkList.Vector 二.Ma ...