Description
Output the answer taken modulo 1234567891.
Input
Technical Specification
1 ≤ T ≤ 10
1 ≤ N ≤ 1,000,000,000
1 ≤ K ≤ 30
Output
Sample Input
Sample Output
题意:求用k种珍珠组成长度为n的项链的个数
思路:用dp[i][j]表示长度为i。j种珍珠的个数。
非常easy推出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;
}
版权声明:本文博客原创文章,博客,未经同意,不得转载。