您的位置:首页 > 其它

BNUOJ28891 Choosing number(矩阵快速幂)

2015-07-22 11:43 357 查看
题目链接:http://www.bnuoj.com/v3/problem_show.php?pid=28891

题意:

有n个人 选择m个数; 每个人可以任意选数 , 若2个相邻的人选择相同的数,当且仅当这个数大于k; 问总共有多少种方法选择数

分析:

对于这道题, 比赛的时候完全没想法, 怎么也没想到是矩阵快速幂;看了别人的博库之后, 仔细想想之后,好像只能用快速幂来做题, 问什么呢? 因为这道题数据很大,普通的方法遍历一次就已经超时了。 搜索更不可能;dp也是遍历的,也是不行。 对于数据很大的我们可以用快速幂来做,以节省时间。 但是普通的快速幂根本没法用。 所以我们看这道题之后, 只找规律了。

对于第一个人, 我们设 x0为选的数不超过k的方法的有几种,设x1为选的数超过k的方法的有几种;

那么对于第二个人来说; y0 = x0*(k-1)+x2*k; y1= x0*(m-k)+x1*(m-k);

在我们找到这个规律之后, 我们就可以很清楚明白用矩阵快速幂了。

下面就是要够造的矩阵

(y0, y1)= (x0, x1) (k-1, m-k)

(k, m-k)

做了这道题, 我又复习了一遍矩阵快速幂; 同时我发现在矩阵乘法中矩阵的顺序对结果是有影响的,就是矩阵乘法中相乘矩阵的位置不能颠倒(自己可以想想为什么)。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int mod = 1000000007;
const int N = 2;
struct Node
{
    int row, cal;
    long long s

;
    Node()
    {
        row = cal = N;
        s[0][0] = 1, s[0][1] = 0;
        s[1][0] = 0, s[1][1] = 1;
    }
};
Node Matble(Node a, Node b)
{
    Node ans;
    ans.row = a.row;
    ans.cal = b.cal;
    for(int i = 0; i < ans.row; i++)
        for(int j = 0; j < ans.cal; j++)
            ans.s[i][j] = 0;
    for(int i = 0; i < ans.row; i++)
    {
        for(int j = 0; j < ans.cal; j++)
        {
            for(int k = 0; k < a.cal; k++)
                ans.s[i][j] = (ans.s[i][j] + a.s[i][k]*b.s[k][j]%mod)%mod;
        }
    }
    return ans;
}
long long pow_Matble(int n, int m, int k)
{
    Node ans, temp, res;
    temp.s[0][0] = k-1, temp.s[0][1] = m-k;
    temp.s[1][0] = k, temp.s[1][1] = m-k;
    while(n)
    {
        if(n&1)
            ans = Matble(ans, temp);
        temp = Matble(temp, temp);
        n >>= 1;
    }
    temp.s[0][0] = k, temp.s[0][1] = m-k;
    temp.s[1][0] = 0, temp.s[1][1] = 0;
    res = Matble(temp, ans);
    long long sum = 0;
    for(int i = 0; i < res.cal; i++)
        sum =(sum + res.s[0][i])%mod;
    return sum;
}
int main()
{
    int n, m, k;
    while(scanf("%d%d%d", &n, &m, &k) != EOF)
    {
        long long ans = pow_Matble(n-1, m, k);
        printf("%lld\n", ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: