[矩阵加速]土豪送项链

题目描述

土豪给心上人做珍珠项链,他有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个珍珠。

经过推算dp[i][j] = (k - (j - 1)) * dp[i - 1][j - 1] + j * dp[i - 1][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。

那么

就很好构造了。

我们的初始矩阵\begin{bmatrix} ans[i] & f[i][1] & f[i][2] & ... & f[i][k] \end{bmatrix}

我们需要转移成这样\begin{bmatrix} ans[i + 1] & f[i + 1][1] & f[i + 1][2] & ... & f[i + 1][k] \end{bmatrix}

那么加速矩阵其实就很好推出来了。

\begin{bmatrix} 1 & 0 & 0 & 0 & . & . & . & & & \\ 0& 1 & (k-1) & 0 & . & . & . & & & \\ 0& 0 & 2 & (k - 2) & . & . & . & & & \\ 0& 0 & 0& 3& . & . & .& & & \\ .& .& .& .& .& .& . & & & \\ .& .& .& .& . & . & . & & & \\ .& .& .& .& .& .& . & & & \\ 0& 0& 0 &0 . & . &. &. & & & \\ 0 & 0& 0& 0&. & . & . & & & \\ 1 & 0& 0& 0& . & . & . & & & \end{bmatrix}

相信你也发现了规律....

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\n",C.c[1][1]);
    }
}

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值