标签:des style os io 数据 for art ar
Description
Input
Output
Sample Input
2 2 1 3 2
Sample Output
2 8
题意:求用k种珍珠组成长度为n的项链的个数
思路:用dp[i][j]表示长度为i,j种珍珠的个数。很容易推出dp[i][j] = dp[i]-1[j]*j+ dp[i-1][j-1]*(k-j+1),因为数据量很大,所以我们需要用矩阵优化,关键构造出矩阵,本来我们是用k维的矩阵构造关系矩阵,但是现在我们要求的是:
dp[1][k]+dp[1][k]+....dp[n][k],所以我们都加一维来记录和。
首先我们利用滚动数组降维的思路构造一个矩阵:f[j] = f[j-1]*j + f[j]*(k-j+1), 因为我们需要的是和以及fk,所以第一维就确定下来了
| 1 0...............0 1 | |g|
| 0 1 0...............0 | |f1|
| 0 k-1 2.............0 | |f2|
| ..................... | * .
| 0...0 k-(j-1) j 0...0| .
| ..................... | .
| 0...............0 1 k | |fk|
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; typedef unsigned long long ll; const int maxn = 35; const int mod = 1234567891; int cnt; struct Matrix { ll v[maxn][maxn]; Matrix() {} Matrix(int x) { init(); for (int i = 0; i < maxn; i++) v[i][i] = x; } void init() { memset(v, 0, sizeof(v)); } Matrix operator *(Matrix const &b) const { Matrix c; c.init(); for (int i = 0; i < cnt; i++) for (int j = 0; j < cnt; j++) for (int k = 0; k < cnt; k++) c.v[i][j] = (c.v[i][j] + (ll)(v[i][k]*b.v[k][j])) % mod; return c; } Matrix operator ^(int b) { Matrix a = *this, res(1); while (b) { if (b & 1) res = res * a; a = a * a; b >>= 1; } return res; } } a, b, tmp; int main() { int t, n, k; scanf("%d", &t); while (t--) { scanf("%d%d", &n, &k); a.init(); a.v[0][0] = a.v[0][k] = 1; for (int j = 1; j <= k; j++) { if (j > 1) a.v[j][j-1] = k-(j-1); a.v[j][j] = j; } cnt = k + 1; ll num[maxn]; memset(num, 0, sizeof(num)); num[1] = k; tmp = a^n; ll ans[maxn]; memset(ans, 0, sizeof(ans)); for (int i = 0; i < cnt; i++) if (num[i]) for (int j = 0; j < cnt; j++) if (tmp.v[j][i]) ans[j] = (ans[j]+ (ll)(tmp.v[j][i]*num[i])) % mod; cout << ans[0] << endl; } return 0; }
HDU - 2294 Pendant (DP滚动数组降维+矩阵快速幂),布布扣,bubuko.com
HDU - 2294 Pendant (DP滚动数组降维+矩阵快速幂)
标签:des style os io 数据 for art ar
原文地址:http://blog.csdn.net/u011345136/article/details/38302753