[HDU2294] Pendant - 矩阵加速递推

Posted zzh-brim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HDU2294] Pendant - 矩阵加速递推相关的知识,希望对你有一定的参考价值。

Pendant

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1032    Accepted Submission(s): 535


Problem Description
On Saint Valentine‘s Day, Alex imagined to present a special pendant to his girl friend made by K kind of pearls. The pendant is actually a string of pearls, and its length is defined as the number of pearls in it. As is known to all, Alex is very rich, and he has N pearls of each kind. Pendant can be told apart according to permutation of its pearls. Now he wants to know how many kind of pendant can he made, with length between 1 and N. Of course, to show his wealth, every kind of pendant must be made of K pearls.
Output the answer taken modulo 1234567891.
 

 

Input
The input consists of multiple test cases. The first line contains an integer T indicating the number of test cases. Each case is on one line, consisting of two integers N and K, separated by one space.
Technical Specification

1 ≤ T ≤ 10
1 ≤ N ≤ 1,000,000,000
1 ≤ K ≤ 30
 

 

Output
Output the answer on one line for each test case.
 

 

Sample Input
2 2 1 3 2
 

 

Sample Output
2 8
 

 

Source
 

 

Recommend
lcy   |   We have carefully selected several similar problems for you:  1588 3117 2971 2256 1757
 

 
题解:
设f[i][j] 表示长度为i,用了j种珍珠的方案个数;
我们考虑加一个位置,我们可以让它是之前出现过的珍珠,也可以是没出现过的珍珠;
f[i][j] = (k-(i-1))*f[i-1][j-1] + j*f[i-1][j];
我们发现这个dp是O(nk)的,n变态的大显然炸掉;
看到n自然而然的会想到矩阵加速;
我们设一个转移矩阵是G,G[k+1][k+1], 为什么是k+1?
我们要算总的方案个数,要把所有的f[i][k]加起来,所以我们多开一维,用来转移f[i][k]的和;
G的矩阵长这样
1 0 0 0 0 1      sum    sum‘  
0 1 0 0 0 1      f1     f1‘
0 k-1 2 0 0 0    *     f2  ->   f2‘
...          ...    ...
0 0 0 0 1 k      fk     fk‘
 
就这样
 

 
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define ll long long
#define mod 1234567891
#define N 32
int T;
ll n, k;

struct Mat
{
    ll a[N][N];
    Mat() {memset(a, 0, sizeof a);}
    inline void clear() {memset(a, 0, sizeof a);}
    inline void ini() {for(int i=0;i<=k;i++)a[i][i]=1;}
    friend Mat operator * (Mat x, Mat y)
    {
        Mat z;
        for (register int p = 0 ; p <= k ; p ++)
        {
            for (register int i = 0 ; i <= k ; i ++)
            {
                for (register int j = 0 ; j <= k ; j ++)
                {
                    z.a[i][j] = (z.a[i][j] + x.a[i][p] * y.a[p][j]) % mod;
                }
            }
        }
        return z;
    }
    friend Mat operator ^ (Mat x, ll y)
    {
        Mat z;z.ini();
        while (y)
        {
            if (y & 1) z = z * x;
            x = x * x;
            y >>= 1;
        }
        return z;
    }
}G, B, C;
inline void init() {G.clear(), B.clear(), C.clear();}

int main()
{
    scanf("%d", &T);
    while (T--)
    {
        init();
        scanf("%lld%lld", &n, &k);
        G.a[0][0] = 1, G.a[0][k] = 1;
        G.a[1][1] = 1;
        for (register int i = 2 ; i <= k ; i ++)
        {
            G.a[i][i] = i;
            G.a[i][i-1] = k - i + 1;
        }
    //    for (int i=0;i<=k;i++,puts(""))for(int j=0;j<=k;j++) printf("%d ",G.a[i][j]) ;
        B.a[1][0] = k;
        C = G ^ n;
        C = C * B;
        cout<<C.a[0][0]<<endl;
    }
    return 0;
}

 

以上是关于[HDU2294] Pendant - 矩阵加速递推的主要内容,如果未能解决你的问题,请参考以下文章

hdu2294:Pendant

HDU 5950 - Recursive sequence - [矩阵快速幂加速递推][2016ACM/ICPC亚洲区沈阳站 Problem C]

[LGOJ]P1939模板矩阵加速(数列)[矩阵加速递推]

POJ3070 Fibonacci(矩阵快速幂加速递推)模板题

矩阵乘法来加速递推式计算

矩阵经典题目七:Warcraft III 守望者的烦恼(矩阵加速递推)