E. Vasya and Magic Matrix

http://codeforces.com/contest/1042/problem/E

题意:

  一个n*m的矩阵,每个位置有一个元素,给定一个起点,每次随机往一个小于这个点位置走,走过去的值为欧几里得距离的平方,求期望的值。

分析:

  逆推期望。

  将所有值取出,按元素大小排序,然后最小的就是0,往所有大于它的转移即可,复杂度n^2,见下方考试代码。

  考虑每个点,从所有小于它的元素转移。排序后,维护前缀和,可以做到O(1)转移。

  $f[i] = \sum\limits_{j=1,val[j]<val[i]}f[j] + (x_j - x_i)^2 + (y_j - y_i) ^ 2$

  $f[i] =\sum\limits_{j=1,val[j]<val[i]} f[j] + x_j^2 - 2x_jx_i + x_i^2 + y_j^2 - 2y_jy_i + y_i ^ 2$

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const LL mod = ;
const int N = ; struct Node {
int x, y, val;
bool zh;
bool operator < (const Node &A) const {
return val < A.val;
}
}A[N];
LL f[N], cnt[N], sumx[N], sumy[N], sumx2[N], sumy2[N]; LL ksm(LL a,LL b) {
LL ans = ;
while (b) {
if (b & ) ans = 1ll * ans * a % mod;
a = 1ll * a * a % mod;
b >>= ;
}
return ans;
} inline void add(LL &x,LL y) { (x += y) >= mod ? (x -= mod) : x; }
inline void sub(LL &x,LL y) { (x -= y) < ? (x += mod) : x; } void solve2(int n) { A[].val = -;
for (int i=; i<=n; ++i) {
if (A[i].val == A[i - ].val) cnt[i] = cnt[i - ];
else cnt[i] = i - ;
sumx[i] = (sumx[i - ] + A[i].x) % mod;
sumy[i] = (sumy[i - ] + A[i].y) % mod;
sumx2[i] = (sumx2[i - ] + 1ll * A[i].x * A[i].x % mod) % mod;
sumy2[i] = (sumy2[i - ] + 1ll * A[i].y * A[i].y % mod) % mod;
} LL sum = , tmp = ;
for (int i=; i<=n; ++i) {
LL x2 = sumx2[cnt[i]];
LL y2 = sumy2[cnt[i]];
LL z1 = 1ll * sumx[cnt[i]] * % mod * A[i].x % mod;
LL z2 = 1ll * sumy[cnt[i]] * % mod * A[i].y % mod;
LL h1 = 1ll * cnt[i] * A[i].x % mod * A[i].x % mod;
LL h2 = 1ll * cnt[i] * A[i].y % mod * A[i].y % mod; add(f[i], x2); add(f[i], y2);
sub(f[i], z1); sub(f[i], z2);
add(f[i], h1); add(f[i], h2);
add(f[i], sum); f[i] = 1ll * f[i] * ksm(cnt[i], mod - ) % mod;
if (A[i].zh) {
cout << f[i]; return ;
}
add(tmp, f[i]); // 只有小于的时候才转移!!!
if (A[i].val < A[i + ].val) add(sum, tmp), tmp = ;
} } int main() {
int n = read(), m = read(), tot = ;
for (int i=; i<=n; ++i)
for (int j=; j<=m; ++j)
A[++tot].x = i, A[tot].y = j, A[tot].val = read(), A[tot].zh = false; int x = read(), y = read(), z = (x - ) * m + y;
A[z].zh = true; sort(A + , A + tot + ); solve2(tot);
return ;
}

比赛时代码,记录调试历程。

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const LL mod = ;
const int N = ; struct Node {
int x, y, val;
bool zh;
bool operator < (const Node &A) const {
return val < A.val;
}
}A[N]; LL inv[N], deg[N], f[N];
//double dp[N]; LL ksm(LL a,LL b) {
LL ans = ;
while (b) {
if (b & ) ans = 1ll * ans * a % mod;
a = 1ll * a * a % mod;
b >>= ;
}
return ans;
} LL Calc(int i,int j) {
return ((A[i].x - A[j].x) * (A[i].x - A[j].x) % mod + (A[i].y - A[j].y) * (A[i].y - A[j].y) % mod) % mod;
} void solve1(int n) {
for (int i=; i<=n; ++i) {
// cout << A[i].val << ": ";
if (deg[i]) {
// dp[i] = dp[i] / (double)(deg[i]);
f[i] = 1ll * ksm(deg[i], mod - ) * f[i] % mod;
}
if (A[i].zh) {
cout << f[i]; return ;
}
for (int j=i+; j<=n; ++j)
if (A[j].val > A[i].val) {
// dp[j] = dp[j] + dp[i] + Calc(i, j);
// cout << A[j].val << " " << Calc(i, j) <<"--";
f[j] = (f[j] + f[i] + Calc(i, j)) % mod;
deg[j] ++;
}
// puts("");
}
} int cnt[N], sumx[N], sumy[N], sumx2[N], sumy2[N]; inline void add(LL &x,LL y) { (x += y) >= mod ? (x -= mod) : x; }
inline void sub(LL &x,LL y) { (x -= y) < ? (x += mod) : x; } void solve2(int n) { A[].val = -;
for (int i=; i<=n; ++i) {
if (A[i].val == A[i - ].val) cnt[i] = cnt[i - ];
else cnt[i] = i - ;
sumx[i] = (sumx[i - ] + A[i].x) % mod;
sumy[i] = (sumy[i - ] + A[i].y) % mod;
sumx2[i] = (sumx2[i - ] + 1ll * A[i].x * A[i].x % mod) % mod;
sumy2[i] = (sumy2[i - ] + 1ll * A[i].y * A[i].y % mod) % mod;
} LL sum = , tmp = ;
for (int i=; i<=n; ++i) {
LL x2 = sumx2[cnt[i]];
LL y2 = sumy2[cnt[i]];
LL z1 = 1ll * sumx[cnt[i]] * % mod * A[i].x % mod;
LL z2 = 1ll * sumy[cnt[i]] * % mod * A[i].y % mod;
LL h1 = 1ll * cnt[i] * A[i].x % mod * A[i].x % mod;
LL h2 = 1ll * cnt[i] * A[i].y % mod * A[i].y % mod; add(f[i], x2); add(f[i], y2);
sub(f[i], z1); sub(f[i], z2);
add(f[i], h1); add(f[i], h2);
add(f[i], sum); f[i] = 1ll * f[i] * ksm(cnt[i], mod - ) % mod;
if (A[i].zh) {
cout << f[i]; return ;
}
add(tmp, f[i]); // 只有小于的时候才转移!!!
if (A[i].val < A[i + ].val) add(sum, tmp), tmp = ;
} } int main() {
int n = read(), m = read(), tot = ;
for (int i=; i<=n; ++i)
for (int j=; j<=m; ++j)
A[++tot].x = i, A[tot].y = j, A[tot].val = read(), A[tot].zh = false; int x = read(), y = read(), z = (x - ) * m + y;
A[z].zh = true; sort(A + , A + tot + ); // if (tot <= 1000) {
// solve1(tot) ;return 0;
// }
solve2(tot);
return ;
}

CF 1042 E. Vasya and Magic Matrix的更多相关文章

  1. CF1042E Vasya and Magic Matrix

    感觉不会期望. 首先把所有格子按照权值从小到大排一下序,这样一共有$n * m$个元素,每个元素有三个属性$x, y, val$. 下文中的下标均为排序后的下标. 这样子我们就可以推出公式: $f_i ...

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

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

  3. CF1042E Vasya and Magic Matrix 题解

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

  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. Codeforces Round #538 (Div. 2) D. Flood Fill 【区间dp || LPS (最长回文序列)】

    任意门:http://codeforces.com/contest/1114/problem/D D. Flood Fill time limit per test 2 seconds memory ...

  2. Linux学习总结(九)-源码包和rpm包安装

    一.源码包安装 通常办法是安装三部曲:./configuremakemake install但是具体还要根据包里面的帮助文档操作./configure --help 可以查看可以带什么参数,比如--p ...

  3. Vue中引入jquery方法 vue-cli webpack 引入jquery

    在vue-cli 生成的工程中引入了jquery(模板用的webpack) 首先在package.json里的dependencies加入"jquery" : "^2.2 ...

  4. svn安装配置

    1. 安装SVN服务器: 检查是否已安装 # rpm -qa subversion 安装SVN服务器 # yum install httpd httpd-devel subversion mod_da ...

  5. PAT——不吉利的日期(java中date和Calendar使用)

    题目描述 在国外,每月的 13 号和每周的星期 5 都是不吉利的.特别是当 13 号那天恰好是星期 5时,更不吉利. 现在给你一个年份,请你从小到大依次输出当年所有13 号是星期 5 的月份. 输入描 ...

  6. Linux环境进程间通信: 共享内存

    Linux环境进程间通信: 共享内存 第一部分 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进 ...

  7. XCode: 如何添加自定义代码片段

    转载自:http://rockonmycode.com/tips/xcode-code-snippets#more-185 我们经常会定义一些retain的property,而且大概每次我们都会像这样 ...

  8. 架构风格:万金油CS与分层

    计算机科学家David Wheele曾说过这么一句话: All problems in computer science can be solved by another level of indir ...

  9. window 下创建软链接 mklink

    软链接是一种文件共享方式. 命令:mklink /d "C:\d" "C:\e" 有哪些坑: 1.此命名必须以管理员方式在cmd运行 2.文件必须不存在..通过 ...

  10. insert插入数据

    insert 语法1 --插入的值需要用单引号引起来,否则字段插入会有问题,可能造成查询的时候查询不出结果 insert  into  表名 (列名1,列名2……)  ] values  ( '值1' ...