CF852B Neural Network country (矩阵优化DP)

题意:
image

思路:
先写一个暴力的dp看能不能优化, f[i][j] 表示到第i层,总路径长度modm的方案数。那么转移;

for ( int i = 1; i <= n; ++ i) {
  for ( int j = 0; j <= m; ++ j ) {
    for ( int k = 0; k <= m; ++ k ) {
      f[i][( j + k ) % m] += f[i - 1][j] * w[k] % mod;
    }
  }
}

如果我们不看第一维: f[( j + k ) % m] += f[j] * w[k]; 这个形式会想到什么?
如果比较熟悉矩阵快速幂,会发现这和矩阵乘法非常像 c[i][j] += a[i][k] * b[k][j];
仿照矩阵快速幂重载f转移的乘法*,O(m * m * logn)地解决。

先写暴力,从暴力入手进行优化,解决问题
1.每次递推都是f[i] * w; 2. c[i][j] += a[i][k] * b[k][j]这种形式。观察到这两点要往矩阵ksm上想

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define PII pair<int, char>
//#define int long long
const int N = 1e6 + 5;
const int M = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
int w[105], m, a[N];
struct matrix {
  int n ;
  ll num[105];
  void clear(){
        memset(num, 0, sizeof num);
  }
  matrix() {
    clear(); n = m;
  }
};
matrix operator *(matrix a, matrix b) {
  matrix c;
  c.n = a.n;
  for(int i = 0; i < a.n; ++ i){
    for(int j = 0; j < a.n; ++ j){
      int k = (i + j) % m;
      c.num[k] = (c.num[k] + a.num[i] * b.num[j] % mod) % mod;     
    }
  }
  return c;
}
matrix qmi(matrix a, ll k){
    matrix ans = a; -- k;
    ans.n = a.n;
    while (k){
        if(k&1) ans = ans * a;
        a = a * a;
        k >>= 1;
    }
    return ans;
}
int main () {
  IOS
  int n, l;
  cin >> n >> l >> m; l -= 2;
  matrix st, b, ed;
  for ( int i = 1; i <= n; ++ i ) {
    int x; cin >> x; ++ st.num[x % m];
  }
  for ( int i = 1; i <= n; ++ i ) {
    int x; cin >> x; a[i] = x; ++ b.num[x % m];
  }
  for ( int i = 1; i <= n; ++ i ) {
    int x; cin >> x; ++ ed.num[(x + a[i]) % m];
  }
  if( l >= 1 ) st = st * qmi(b, l);
  st = st *  ed;
  cout << st.num[0] << '\n';
  return 0;
}
posted @ 2022-07-04 20:34  qingyanng  阅读(31)  评论(0编辑  收藏  举报