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 = 1005;
const int M = 1e6 + 5;
const ll P = 998244353LL;

int n, m, tot = 0;
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 > 0; y >>= 1) {
        if(y & 1) 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 = 0; char ch = 0; T op = 1;
    for(; ch > ‘9‘ || ch < ‘0‘; ch = getchar())
        if(ch == ‘-‘) op = -1;
    for(; ch >= ‘0‘ && ch <= ‘9‘; ch = getchar())
        X = (X << 3) + (X << 1) + ch - 48;
    X *= op;
}

int main() {
    read(n), read(m);
    for(int i = 1; i <= n; i++)
        for(int j = 1; 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 + 1, b + 1 + tot, cmp);
    for(int i = 1; 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 = 0;
    for(int i = 1; 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 <= 1) continue;
        ll invK = fpow(k - 1, P - 2);
        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 0;
}

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

原文地址:https://www.cnblogs.com/CzxingcHen/p/9680254.html

时间: 2024-11-14 12:44:35

CF1042E Vasya and Magic Matrix的相关文章

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

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

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

D. Vasya And The Matrix time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard output Now Vasya is taking an exam in mathematics. In order to get a good mark, Vasya needs to guess the matrix that the teache

D. Vasya And The Matrix

time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Now Vasya is taking an exam in mathematics. In order to get a good mark, Vasya needs to guess the matrix that the teacher has constructed! V

(最小生成树)Codeforces Educational Codeforces Round 9 Magic Matrix

You're given a matrix A of size n?×?n. Let's call the matrix with nonnegative elements magic if it is symmetric (so aij?=?aji), aii?=?0 and aij?≤?max(aik,?ajk) for all triples i,?j,?k. Note that i,?j,?k do not need to be distinct. Determine if the ma

codeforces 632F. Magic Matrix

题目链接 给一个n*n的矩阵, 问是否对角线上的元素全都为0, a[i][j]是否等于a[j][i], a[i][j]是否小于等于max(a[i][k], a[j][k]), k为任意值. 前两个都好搞, 我们来看第三个. 第三个的意思是, 对于a[i][j], 它小于等于第i行和第j行每一列的两个元素的最大值. 我们将矩阵中的每一个元素的值以及x, y坐标都加到一个数组里面, 然后从小到大排序. 从0到n-1枚举每一个i, 如果一个元素pos比i小, 那么就将b[pos的x][pos的y]这个

CodeForces - 1016D Vasya And The Matrix

题面在这里! 很明显二进制每一位都是无关的,所以可以先把原问题简化:给矩阵中的每个位置填入0/1,使得特定行/列有奇数个1,其他行/列有偶数个1. 一个比较好想的方法是对行和列 列出 n+m 个异或方程,其中有 n*m 个变量,随便求出一组解就好了(如果有的话). 但这个貌似并不是很好写... 可以把解异或方程转化成 在一个完全二分图(左n个点,右m个点)上选边,每个点可以是黑的(对应行/列要求有奇数个1)或者白的(反之),每选一条边就要把两端的点的黑白性颠倒. 然后发现这是一个经典问题,显然选

Destroy Tunnels(矩阵水题)

Destroy Tunnels Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 39  Solved: 22 [Submit][Status][Web Board] Description Zuosige always has bad luck. Recently, he is in hospital because of pneumonia. While he is taking his injection, he feels extremely

MATLAB conv2卷积的实现

二维卷积的算法原理比較简单,參考随意一本数字信号处理的书籍,而matlab的conv2函数的滤波有个形状參数,用以下的一张图非常能说明问题: 这里给出一种最原始的实现方案.这样的实现对于数据矩阵大小为1000x1000,卷积核矩阵大小为20x20,在我的机器上须要大约1秒钟的时间.而matlab採用的MKL库最快仅仅须要将近0.1s的时间. 以下的代码用到了自己眼下开发的FastIV中的一些函数接口.详细代码例如以下: #include "fiv_core.h" typedef enu

CSU1612: Destroy Tunnels

Description Zuosige always has bad luck. Recently, he is in hospital because of pneumonia. While he is taking his injection, he feels extremely bored. However, clever Zuosige comes up with a new game. Zuosige is playing a computer game called Call of