hdu2294---Pendant (矩阵)

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

The 4th Baidu Cup final

Recommend

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

dp[i][j]表示长度为i,有j种珍珠的吊坠的数目

dp[i][j] = (k - j + 1) * dp[i - 1][j - 1] + j * dp[i - 1][j];

n太大,考虑用矩阵

由于每一个状态只和长度比他小1的状态有关,可以降到一维

设矩阵fn 表示 长度为n的吊坠的数目(0种珍珠,1种珍珠, ….. k种珍珠)

fn:

dp[0] dp[1] ….. dp[k]

0 0 ….. 0

… .. … 0

0 0 …. 0

构造这样一个(k+1)*(k+1)的矩阵

fn = fn-1 A = f1 A^(n-1)

sum = f1 + f2 + … + fn = (E + A + … + A ^(n - 1)) * f1

根据递推关系可得

A:

 0 k …… …. 0

  0 1 k - 1 … 0

  0 0 2 k - 2 0

  …………………..

  0 0 ….. …… k

显然f1就等于A

则sum(n) = (A + A^2 + …. + A^n) = (E + A^(n / 2)) * (A + A ^ 2 + … + A ^ (n / 2)) + (n & 1) ? A^n : 0

斜体加粗部分就是sum(n / 2)

二分就行

/*************************************************************************
    > File Name: hdu2294.cpp
    > Author: ALex
    > Mail: [email protected]
    > Created Time: 2015年03月11日 星期三 15时52分41秒
 ************************************************************************/

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;

const int mod = 1234567891;

int k;

struct MARTIX
{
    LL mat[32][32];
    int n;

    void init(int _n)
    {
        n =_n;
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                mat[i][j] = 0;
            }
        }
    }

    MARTIX operator + (const MARTIX &b) const
    {
        MARTIX res;
        res.n = b.n;
        for (int i = 0; i < b.n; ++i)
        {
            for (int j = 0; j < b.n; ++j)
            {
                res.mat[i][j] = mat[i][j] + b.mat[i][j];
                res.mat[i][j] %= mod;
            }
        }
        return res;
    }

    MARTIX operator * (const MARTIX &b)const
    {
        MARTIX res;
        res.n = b.n;
        for (int i = 0; i < b.n; ++i)
        {
            for (int j = 0; j < b.n; ++j)
            {
                res.mat[i][j] = 0;
                for (int l = 0; l < b.n; ++l)
                {
                    res.mat[i][j] += mat[i][l] * b.mat[l][j];
                    res.mat[i][j] %= mod;
                }
            }
        }
        return res;
    }

    MARTIX & operator = (const MARTIX & b)
    {
        this -> n = b.n;
        for (int i = 0; i < b.n; ++i)
        {
            for (int j = 0; j < b.n; ++j)
            {
                this -> mat[i][j] = b.mat[i][j];
            }
        }
        return *this;
    }
}A, E;

MARTIX fastpow(MARTIX ret, int n)
{
    MARTIX ans;
    ans.init(k + 1);
    for (int i = 0; i < ans.n; ++i)
    {
        for (int j = 0; j < ans.n; ++j)
        {
            ans.mat[i][j] = (i == j);
        }
    }
    while(n)
    {
        if (n & 1)
        {
            ans = ans * ret;
        }
        n >>= 1;
        ret = ret * ret;
    }
    return ans;
}

void Debug(MARTIX A)
{
    for (int i = 0; i < A.n; ++i)
    {
        for (int j = 0; j < A.n; ++j)
        {
            printf("%lld ", A.mat[i][j]);
        }
        printf("\n");
    }
}

MARTIX binsearch(int cnt)
{
    if (cnt == 1)
    {
        return A;
    }
    MARTIX tmp = binsearch(cnt >> 1);
    MARTIX c = fastpow(A, cnt >> 1);
    c = c + E;
    tmp = c * tmp;
    if (cnt & 1)
    {
        MARTIX d = fastpow(A, cnt);
        tmp = tmp + d;
    }
    return tmp;
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        int n;
        scanf("%d%d", &n, &k);
        A.init(k + 1);
        E.init(k + 1);
        for (int i = 0; i < E.n; ++i)
        {
            for (int j = 0; j < E.n; ++j)
            {
                E.mat[i][j] = (i == j);
            }
        }
        A.mat[0][0] = 0;
        A.mat[0][1] = k;
        for (int i = 1; i < A.n; ++i)
        {
            A.mat[i][i] = i;
            if (i + 1 < A.n)
            {
                A.mat[i][i + 1] = k - i;
            }
        }
        MARTIX ans;
        ans.init(k + 1);
        ans = binsearch(n);
//      Debug(ans);
        printf("%lld\n", ans.mat[0][k]);
    }
    return 0;
}
时间: 2024-11-10 08:18:52

hdu2294---Pendant (矩阵)的相关文章

[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 f

HDU 2294 Pendant (DP+矩阵快速幂降维)

HDU 2294 Pendant (DP+矩阵快速幂降维) ACM 题目地址:HDU 2294 Pendant 题意: 土豪给妹子做首饰,他有K种珍珠,每种N个,为了炫富,他每种珍珠都要用上.问他能做几种长度[1,N]的首饰. 分析: 1 ≤ N ≤ 1,000,000,000简直可怕. 首先想dp,很明显可以想到: dp[i][j] = (k-(j-1))*dp[i-1][j-1] + j*dp[i-1][j](dp[i][j]表示长度为i的并且有j种珍珠的垂饰有多少个) 然后遇到N太大的话,

HDU - 2294 Pendant (DP滚动数组降维+矩阵快速幂)

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, Ale

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 <cst

hdu2294:Pendant

T<=10组数据问K<=30种珠子每种n<=1e9串成1~n长度的序列共有多少种,mod1234567891. 方程没想到.矩阵不会推.很好. f[i][j]--长度i,j种珠子方案数,f[i][j]=f[i-1][j]*j(放个旧的)+f[i-1][j-1]+(K-(j-1))(放个新的) n太大,推不动.由于f[i-1]->f[i],考虑矩乘优化.设递推用的矩阵为A.F[i]表示f[i][1]~f[i][k]. 方法一:f加多一个数表示ans,初始化{0,k,0,0,--},那

HDU2294--Pendant(DP,矩阵优化)

Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 107 Accepted Submission(s): 69 Problem Description On Saint Valentine's Day, Alex imagined to present a special pendant to his girl friend made by K

Pendant

Pendant Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 104 Accepted Submission(s): 66   Problem Description On Saint Valentine's Day, Alex imagined to present a special pendant to his girl friend

矩阵乘法的Strassen算法详解

题目描述 请编程实现矩阵乘法,并考虑当矩阵规模较大时的优化方法. 思路分析 根据wikipedia上的介绍:两个矩阵的乘法仅当第一个矩阵B的列数和另一个矩阵A的行数相等时才能定义.如A是m×n矩阵和B是n×p矩阵,它们的乘积AB是一个m×p矩阵,它的一个元素其中 1 ≤ i ≤ m, 1 ≤ j ≤ p. 值得一提的是,矩阵乘法满足结合律和分配率,但并不满足交换律,如下图所示的这个例子,两个矩阵交换相乘后,结果变了: 下面咱们来具体解决这个矩阵相乘的问题. 解法一.暴力解法 其实,通过前面的分析

*C#(WPF)--矩阵拖动和矩阵动画(拖动展开,不足动画效果)

最近在研发新的项目,遇到了一个桌面模式下的难点--展开动画.之前动画这方面没做过,也许很多人开始做的时候也会遇到相关问题,因此我把几个重点及实际效果图总结展示出来: 我的开发环境是在VS2017下进行的,这个工具条主要功能是:一个工具条,可进行拖拉.可进行拖拉展开,可在拖动之后不足展开并反向继续展开剩下的部分: 一.[拖动]   拖动的核心代码是通过矩阵进行定位和拖动的,定位是以父容器为模板的.以下是核心代码(及效果图): 1 /// <summary> 2 /// 这里TitleBar代指最