标签: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