期望dp ---- E. Vasya and Magic Matrix(二维转一维+前缀和优化的期望dp)

题目链接


题目大意:

在这里插入图片描述


解题思路:

  1. 首先我们先把二维矩阵变成一维的 ( x , y ) → ( x − 1 ) ⋅ m + y (x,y)\rightarrow(x-1)\cdot m+y (x,y)(x1)m+y
  2. 然后对每个点按照权值排序从小到大去枚举
  3. f [ i ] = ∑ j ( x i − x j ) 2 + ( y i − y j ) 2 + f [ j ] m f[i]=\sum_{j}\frac{(x_i-x_j)^2+(y_i-y_j)^2+f[j]}{m} f[i]=jm(xixj)2+(yiyj)2+f[j]
  4. f [ i ] 是 第 i 个 点 出 发 的 期 望 得 分 f[i]是第i个点出发的期望得分 f[i]i
  5. m 是 权 值 比 i 小 的 点 的 个 数 m是权值比i小的点的个数 mi
  6. 这个式子很不好求
  7. 我们展开看看
  8. m ⋅ x i 2 + m ⋅ y i 2 + ( x j 1 2 + x j 2 2 . . . . . ) + ( y j 1 2 + y j 2 2 . . . . . ) − 2 ⋅ ( x j 1 + x j 2 . . . . . ) ∗ x i − 2 ⋅ ( y j 1 + y j 2 . . . . . ) ∗ y i + ( f [ j 1 ] + f [ j 2 ] . . . . . ) m\cdot x_i^2+m\cdot y_i^2+(x^2_{j1}+x^2_{j2}.....)+(y^2_{j1}+y^2_{j2}.....)-2\cdot(x_{j1}+x_{j2}.....)*x_i-2\cdot(y_{j1}+y_{j2}.....)*y_i+(f[j1]+f[j2].....) mxi2+myi2+(xj12+xj22.....)+(yj12+yj22.....)2(xj1+xj2.....)xi2(yj1+yj2.....)yi+(f[j1]+f[j2].....)
  9. 我们发现上面的式子可以前缀和预处理的 → x 2 , y 2 , x , y , f \rightarrow x^2,y^2,x,y,f x2,y2,x,y,f
  10. 我们还要预处理逆元

AC code

#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 998244353;
const int maxn = 2e6 +10;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {
   x = 0;char ch = getchar();ll f = 1;
   while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
   while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {
   read(first);
   read(args...);
}

int n, m, x, y;
int prex2[maxn], prey2[maxn], predp[maxn], dp[maxn], prex[maxn], prey[maxn], inv[maxn];
inline void add(int &x, int y) {
   x += y;
   if(x >= mod) x -= mod;
   if(x < 0) x += mod;
}
struct node {
   int x, y;
   int val;
   bool operator < (const node & a) const {
      return val < a.val;
   }
}matrix[N];

ll qmi(ll a, ll b) {
   int res = 1;
   while(b) {
      if(b & 1) res = res * a % mod;
      a = a * a % mod;
      b >>= 1;
   }
   return res % mod;
}

int main() {
    read(n,m);
    for(int i = 1; i <= n; ++ i) 
       for(int last = 1; last <= m; ++ last) {
          int val;
          cin >> val;
          matrix[(i-1)*m+last] = {i,last,val};
       }

    inv[1] = 1;// 逆元处理
    for (int i = 2; i <= n * m; ++i) {
      inv[i] = (long long)(mod - mod / i) * inv[mod % i] % mod;
    }
    read(x,y);
    sort(matrix+1,matrix+1+n*m);
    int last = 0;//保存第一个严格小与当前数的位置
    for(int i = 1; i <= n * m; ++ i) {
        if(matrix[i].val != matrix[i-1].val) last = i-1;
        add(dp[i],predp[last]);
        add(dp[i],1ll*last*matrix[i].x*matrix[i].x%mod);
        add(dp[i],1ll*last*matrix[i].y*matrix[i].y%mod);
        add(dp[i],prex2[last]);
        add(dp[i],prey2[last]);
        add(dp[i],-2ll*prex[last]*matrix[i].x%mod);
        add(dp[i],-2ll*prey[last]*matrix[i].y%mod);
        dp[i] = 1ll * dp[i] * inv[last] % mod;
        if(matrix[i].x == x && matrix[i].y == y) {
           cout << (dp[i] % mod + mod) % mod;
           return 0;
        }
        predp[i] = (predp[i-1] + dp[i]) % mod;
        prex2[i] = (prex2[i-1] + matrix[i].x*matrix[i].x) % mod;
        prey2[i] = (prey2[i-1] + matrix[i].y*matrix[i].y) % mod;
        prex[i] = (prex[i-1] + matrix[i].x) % mod;
        prey[i] = (prey[i-1] + matrix[i].y) % mod;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值