CF852B Neural Network country (矩阵优化DP)
题意:
思路:
先写一个暴力的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;
}