题目描述
土豪给心上人做珍珠项链,他有K种珍珠,每种N颗,为了炫富,他每种珍珠都要用上。问他能做几种长度[1,N]的首饰。答案要模1234567891。
输入
第一行输入一个T(代表T组数据)
接下来T行,每行一个N,一个K,用空格隔开
1 ≤ T ≤ 10
1 ≤ N ≤ 1,000,000,000
1 ≤ K ≤ 30
输出
共T行
每行一个对应N,K的结果
样例输入
2 2 1 3 2
样例输出
2 8
温馨提醒您:
数据千万条,清零第一条,多测不清零,爆零两行泪
样例解释:
第一组数据:N=1,K=1时只有1种;N=2,K=1时只有1种,所以一共是2种
第二组数据:N=1,K=2时0种;N=2,K=2时有2种;N=3,K=2时有6种,所以一共是8种
are you 明白?
解题思路
首先我们这道题很明显是一个dp,可以说是双重DP。
我们先设一个ans[i]表示当[1,i]的方案总数。
那么很显然。ans[i] = dp[1][k] + dp[2][k].... + dp[i][k]。
我们就需要求出dp[i][j].
dp[i][j]表示长度为i,j个珍珠。
经过推算。
如何理解呢,我们想一下,如果需要长度为i,并且用到j个珍珠,那么它可以是两种状态转移过来
1.长度为i - 1的用了j - 1种珍珠,那么只能在(k - (j - 1))中选一种珍珠,于是乘dp[i - 1][j - 1]。
2.长度为i - 1的用了j种珍珠,那么只能再在这j种珍珠中再选一种来用,于是就是dp[i - 1][j] * j。
那么
就很好构造了。
我们的初始矩阵
我们需要转移成这样
那么加速矩阵其实就很好推出来了。
相信你也发现了规律....
int main(){
scanf ("%d",&t);
while (t -- ){
memset(A.c,0,sizeof(A.c));
memset(B.c,0,sizeof(B.c));
memset(C.c,0,sizeof(C.c));
scanf ("%d%d",&n,&k);
A.n = 1;
A.m = k + 1;
A.c[1][1] = 0;
A.c[1][2] = k;
B.n = B.m = k + 1;
B.c[1][1] = B.c[k + 1][1] = 1;
for (int i = 2;i <= k + 1;i ++){
B.c[i][i] = i - 1;
B.c[i][i + 1] = k - (i - 1);
}
C = A * qkpow(B,n);
printf("%lld
",C.c[1][1]);
}
}