1. 程式人生 > >CF 1042 E. Vasya and Magic Matrix

CF 1042 E. Vasya and Magic Matrix

mat ret dig end getc 復雜 lse show color

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$

代碼:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<cctype>
 7 #include<set>
 8
#include<vector> 9 #include<queue> 10 #include<map> 11 #define fi(s) freopen(s,"r",stdin); 12 #define fo(s) freopen(s,"w",stdout); 13 using namespace std; 14 typedef long long LL; 15 16 inline int read() { 17 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if
(ch==-)f=-1; 18 for(;isdigit(ch);ch=getchar())x=x*10+ch-0;return x*f; 19 } 20 21 const LL mod = 998244353; 22 const int N = 1000010; 23 24 struct Node { 25 int x, y, val; 26 bool zh; 27 bool operator < (const Node &A) const { 28 return val < A.val; 29 } 30 }A[N]; 31 LL f[N], cnt[N], sumx[N], sumy[N], sumx2[N], sumy2[N]; 32 33 LL ksm(LL a,LL b) { 34 LL ans = 1; 35 while (b) { 36 if (b & 1) ans = 1ll * ans * a % mod; 37 a = 1ll * a * a % mod; 38 b >>= 1; 39 } 40 return ans; 41 } 42 43 inline void add(LL &x,LL y) { (x += y) >= mod ? (x -= mod) : x; } 44 inline void sub(LL &x,LL y) { (x -= y) < 0 ? (x += mod) : x; } 45 46 void solve2(int n) { 47 48 A[0].val = -1; 49 for (int i=1; i<=n; ++i) { 50 if (A[i].val == A[i - 1].val) cnt[i] = cnt[i - 1]; 51 else cnt[i] = i - 1; 52 sumx[i] = (sumx[i - 1] + A[i].x) % mod; 53 sumy[i] = (sumy[i - 1] + A[i].y) % mod; 54 sumx2[i] = (sumx2[i - 1] + 1ll * A[i].x * A[i].x % mod) % mod; 55 sumy2[i] = (sumy2[i - 1] + 1ll * A[i].y * A[i].y % mod) % mod; 56 } 57 58 LL sum = 0, tmp = 0; 59 for (int i=1; i<=n; ++i) { 60 LL x2 = sumx2[cnt[i]]; 61 LL y2 = sumy2[cnt[i]]; 62 LL z1 = 1ll * sumx[cnt[i]] * 2 % mod * A[i].x % mod; 63 LL z2 = 1ll * sumy[cnt[i]] * 2 % mod * A[i].y % mod; 64 LL h1 = 1ll * cnt[i] * A[i].x % mod * A[i].x % mod; 65 LL h2 = 1ll * cnt[i] * A[i].y % mod * A[i].y % mod; 66 67 add(f[i], x2); add(f[i], y2); 68 sub(f[i], z1); sub(f[i], z2); 69 add(f[i], h1); add(f[i], h2); 70 add(f[i], sum); 71 72 f[i] = 1ll * f[i] * ksm(cnt[i], mod - 2) % mod; 73 if (A[i].zh) { 74 cout << f[i]; return ; 75 } 76 add(tmp, f[i]); // 只有小於的時候才轉移!!! 77 if (A[i].val < A[i + 1].val) add(sum, tmp), tmp = 0; 78 } 79 80 } 81 82 int main() { 83 int n = read(), m = read(), tot = 0; 84 for (int i=1; i<=n; ++i) 85 for (int j=1; j<=m; ++j) 86 A[++tot].x = i, A[tot].y = j, A[tot].val = read(), A[tot].zh = false; 87 88 int x = read(), y = read(), z = (x - 1) * m + y; 89 A[z].zh = true; 90 91 sort(A + 1, A + tot + 1); 92 93 solve2(tot); 94 return 0; 95 }

比賽時代碼,記錄調試歷程。

技術分享圖片
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<cctype>
  7 #include<set>
  8 #include<vector>
  9 #include<queue>
 10 #include<map>
 11 #define fi(s) freopen(s,"r",stdin);
 12 #define fo(s) freopen(s,"w",stdout);
 13 using namespace std;
 14 typedef long long LL;
 15 
 16 inline int read() {
 17     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1;
 18     for(;isdigit(ch);ch=getchar())x=x*10+ch-0;return x*f;
 19 }
 20 
 21 const LL mod = 998244353;
 22 const int N = 1000010;
 23 
 24 struct Node {
 25     int x, y, val;
 26     bool zh;
 27     bool operator < (const Node &A) const {
 28         return val < A.val;
 29     }
 30 }A[N];
 31 
 32 LL inv[N], deg[N], f[N];
 33 //double dp[N];
 34 
 35 LL ksm(LL a,LL b) {
 36     LL ans = 1;
 37     while (b) {
 38         if (b & 1) ans = 1ll * ans * a % mod;
 39         a = 1ll * a * a % mod;
 40         b >>= 1;
 41     }
 42     return ans;
 43 }
 44 
 45 LL Calc(int i,int j) {
 46     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;
 47 }
 48 
 49 void solve1(int n) {
 50     for (int i=1; i<=n; ++i) {
 51 //        cout << A[i].val << ": ";
 52         if (deg[i]) {
 53 //            dp[i] = dp[i] / (double)(deg[i]);
 54             f[i] = 1ll * ksm(deg[i], mod - 2) * f[i] % mod;
 55         }
 56         if (A[i].zh) {
 57             cout << f[i]; return ;
 58         }
 59         for (int j=i+1; j<=n; ++j) 
 60             if (A[j].val > A[i].val) {
 61 //                dp[j] = dp[j] + dp[i] + Calc(i, j);
 62 //                cout << A[j].val << " " << Calc(i, j) <<"--";
 63                 f[j] = (f[j] + f[i] + Calc(i, j)) % mod;
 64                 deg[j] ++;
 65             }
 66 //        puts("");
 67     }
 68 }
 69 
 70 int cnt[N], sumx[N], sumy[N], sumx2[N], sumy2[N];
 71 
 72 inline void add(LL &x,LL y) { (x += y) >= mod ? (x -= mod) : x; }
 73 inline void sub(LL &x,LL y) { (x -= y) < 0 ? (x += mod) : x; }
 74 
 75 void solve2(int n) {
 76     
 77     A[0].val = -1;
 78     for (int i=1; i<=n; ++i) {
 79         if (A[i].val == A[i - 1].val) cnt[i] = cnt[i - 1];
 80         else cnt[i] = i - 1;
 81         sumx[i] = (sumx[i - 1] + A[i].x) % mod;
 82         sumy[i] = (sumy[i - 1] + A[i].y) % mod;
 83         sumx2[i] = (sumx2[i - 1] + 1ll * A[i].x * A[i].x % mod) % mod;
 84         sumy2[i] = (sumy2[i - 1] + 1ll * A[i].y * A[i].y % mod) % mod;
 85     }
 86     
 87     LL sum = 0, tmp = 0;
 88     for (int i=1; i<=n; ++i) {
 89         LL x2 = sumx2[cnt[i]];
 90         LL y2 = sumy2[cnt[i]];
 91         LL z1 = 1ll * sumx[cnt[i]] * 2 % mod * A[i].x % mod;
 92         LL z2 = 1ll * sumy[cnt[i]] * 2 % mod * A[i].y % mod;
 93         LL h1 = 1ll * cnt[i] * A[i].x % mod * A[i].x % mod;
 94         LL h2 = 1ll * cnt[i] * A[i].y % mod * A[i].y % mod;
 95         
 96         add(f[i], x2); add(f[i], y2); 
 97         sub(f[i], z1); sub(f[i], z2);
 98         add(f[i], h1); add(f[i], h2);
 99         add(f[i], sum);
100         
101         f[i] = 1ll * f[i] * ksm(cnt[i], mod - 2) % mod;
102         if (A[i].zh) {
103             cout << f[i]; return ;
104         }
105         add(tmp, f[i]); // 只有小於的時候才轉移!!! 
106         if (A[i].val < A[i + 1].val) add(sum, tmp), tmp = 0;
107     }
108     
109 }
110 
111 int main() {
112     int n = read(), m = read(), tot = 0;
113     for (int i=1; i<=n; ++i) 
114         for (int j=1; j<=m; ++j) 
115             A[++tot].x = i, A[tot].y = j, A[tot].val = read(), A[tot].zh = false;
116     
117     int x = read(), y = read(), z = (x - 1) * m + y;
118     A[z].zh = true;
119     
120     sort(A + 1, A + tot + 1);
121     
122     
123 //    if (tot <= 1000) {
124 //        solve1(tot) ;return 0;
125 //    }
126     solve2(tot);
127     return 0;
128 }
View Code

CF 1042 E. Vasya and Magic Matrix