首页 > 代码库 > HDOJ 2294 - Pendant(DP+矩阵快速幂)

HDOJ 2294 - Pendant(DP+矩阵快速幂)

题目链接


题意:有个高富帅,要送个很装逼的吊坠给他女朋友。他有k种珠子,然后要串成一个珠子个数小于等于n 的链子(k种珠子都必须要用到)。输入n和k,输出他可以做出多少种不一样的项链。

思路:可以想到递推式f(x, y) = f(x – 1, y) * y + f(x – 1, y – 1) * (k – y + 1)(表示x个珠子用了y种类型),因为n过大,无法直接求出来,所以要使用矩阵快速幂。

GG队友的思路

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

typedef long long ll;

const int MOD = 1234567891;
const int MAXN = 35;

struct mat{
    ll s[MAXN][MAXN];
    mat() {
        memset(s, 0, sizeof(s)); 
    }
    mat operator * (const mat& c) {
        mat ans; 
        memset(ans.s, 0, sizeof(ans.s));
        for (int i = 0; i < MAXN; i++) 
            for (int j = 0; j < MAXN; j++) 
                for (int k = 0; k < MAXN; k++) 
                    ans.s[i][j] = (ans.s[i][j] + s[i][k] * c.s[k][j]) % MOD;
        return ans;
    }
    void put() {
        for (int i = 0; i < MAXN; i++) {
            for (int j = 0; j < MAXN; j++)  
                printf("%lld ", s[i][j]);
            printf("\n");
        }
    }
}c;

ll n;
int k;

void init() {
    memset(c.s, 0, sizeof(c.s));
    c.s[0][0] = 1;  
    c.s[k][0] = 1;  
    for (int i = 1; i < k + 1; i++) {  
        c.s[i][i] = i;  
        if (i > 1) 
            c.s[i - 1][i] = k - i + 1;  
    }  
}

mat pow_mod(ll n) {
    if (n == 1)
        return c;
    mat a = pow_mod(n / 2);
    mat ans = a * a;
    if (n % 2)
        ans = ans * c;
    return ans;
}

int main() {
    int cas;
    scanf("%d", &cas);
    while (cas--) {
        scanf("%lld%d", &n, &k);    
        init();
        mat ans = pow_mod(n);
        printf("%lld\n", k * ans.s[1][0] % MOD);
    }
    return 0;
}


HDOJ 2294 - Pendant(DP+矩阵快速幂)