• [矩阵加速]土豪送项链


    题目描述

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

    那么

    就很好构造了。

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

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

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

    egin{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
    ",C.c[1][1]);
        }
    }
  • 相关阅读:
    把手机用户的身份验证简化到极致 – IEMI
    WIFI 功放芯片确定功率大小
    告别镜像端口:完成流量监控全功略
    windows 2003 server 配置为NTP服务器
    【转】VIM 多文件跳转
    【转】在Linux下FQ的看过来
    【转】VIM自动完成
    【转】VIM下的跳转练习
    【转】vim 窗口调整
    【转】Cscope的使用(领略Vim + Cscope的强大魅力)
  • 原文地址:https://www.cnblogs.com/lover-fucker/p/13566682.html
Copyright © 2020-2023  润新知