您的位置:首页 > 其它

hdu 4602(推公式、矩阵快速幂)

2018-01-28 19:55 399 查看
/*

    hdu 4602

    题目大意是

    将一个数n写成多个整数相加的形式

    问所有式子里面1、2、3……n有多少个

    1-5的所有组合可以写成一下形式

         1   2   3   4   5

    1    1   2   5   12  28

    2        1   2   5   12

    3            1   2   5

    4                1   2

    5                    1

    我们横着看每一行可以找到规律

    f(x)=2*f(x-1)+2^(x-3)(x>=3)

    竖着看可以发现,和横着逆时针旋转90度是一样的

    也就是说对于n==5而言

    第一列与第五行是相等的,第二列与第四行是相等的

    我们可以找到规律,若第i行和第j列相等

    则i+j==n+1

    现在题目给了第k行,则我们可以先求出是第几列

    然后套用上面找到的公式

    注意特判:

    1.行数最大值一定与列数相等,若给定的行数k>n则不存在

    2。求出来的列数是1或者2时不符合上述规律

    之后矩阵快速幂即可

*/

#include <iostream>

#include <stdio.h>

#include <algorithm>

#include <math.h>

#include <string.h>

#define pi acos(-1.0)

#define ll long long

#define MAX 3

#define mod 1000000007

using namespace std;

struct matrix

{

    ll m[MAX][MAX];

};

matrix matrixmul(matrix a,matrix b)

{

    matrix c;

    for(int i=1; i<=2; i++)

        for(int j=1; j<=2; j++)

        {

            c.m[i][j]=0;

            for(int k=1; k<=2; k++)

                c.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;

            c.m[i][j]%=mod;

        }

    return c;

}

matrix quickpow(matrix m,int n)

{

    matrix b;

    memset(b.m,0,sizeof(b.m));

    for(int i = 1; i <= 2; i++)

        b.m[i][i] = 1;

    while(n>=1)

    {

        if(n&1)

            b=matrixmul(b,m);

        n=n>>1;

        m=matrixmul(m,m);

    }

    return b;

}

int main()

{

    int t;

    cin>>t;

    while(t--)

    {

        matrix m;

        m.m[1][1]=2;

        m.m[1][2]=1;

        m.m[2][1]=0;

        m.m[2][2]=2;

        int n,k;

        cin>>n>>k;

        if(k>n)

        {

            cout<<0<<endl;

            continue;

        }

        int cnt=n-k+1;

        if(cnt==1)

        {

            cout<<1<<endl;

            continue;

        }

        if(cnt==2)

        {

            cout<<2<<endl;

            continue;

        }

        matrix res=quickpow(m,cnt-2);

        ll ans=((res.m[1][1]*2)%mod+res.m[1][2])%mod;

        cout<<ans<<endl;

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: