2017暑期ACM俱乐部个人训练赛第5场 G.礼物 (矩阵快速幂)

问题 G: 礼物

时间限制: 5 Sec  内存限制: 512 MB
提交: 76  解决: 23
[提交][状态][讨论版]

题目描述

热情好客的小猴请森林中的朋友们吃饭,他的朋友被编号为 1∼N,每个到来的朋友都会带给他一些礼物:香蕉。其中,第一个朋友会带给他1个香蕉,之后,每一个朋友到来以后,都会带给他之前所有人带来的礼物个数再加他的编号的K次方那么多个。所以,假设 K=2,前几位朋友带来的礼物个数分别是:
1,5,15,37,83,…
假设 K=3,前几位朋友带来的礼物个数分别是:
1,9,37,111,…
现在,小猴好奇自己到底能收到第 N 个朋友多少礼物,因此拜托于你了。
已知 N,K,请输出第 N 个朋友送的礼物个数 mod 1000000007

输入

第一行,两个整数 N,K。

输出

一个整数,表示第N个朋友送的礼物个数 mod 1000000007。

样例输入

4 2

样例输出

37

提示

100% 的数据:N≤1018,K≤10。


123

分析:  对于 第n 个人说   送的数目 an =  S(n-1) +n^k;  则 前 n 个人送的总数目 S(N)  = S(N-1) + aN;  于是有  S(N)=  2*S(N-1) + n^k;

构造矩阵:



于是 先打表 k的组合数;  然后 进行矩阵快速幂;

套模板

代码;

#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <stdio.h>
#include <cmath>
#include <string>
#include <stack>

typedef long long ll;

const int MOD=1000000007;
const int N =20;
const int MAXN=11;
using namespace std;
ll c[20][20];
ll n;
int k;
ll myc(int  n,int  r)
{
	ll sum=1;
	for(int i=1;i<=r;i++)
		sum=sum*(n+1-i)/i;
	return sum;
}
void init_tab()
{
    memset(c,0,sizeof(c));
    for(int i=1;i<=10;i++)
        for(int j=0;j<=i;j++)
    {
        c[i][j]=myc(i,j);
    }

//     for(int i=1;i<=10;i++)
//     {
//         for(int j=0;j<=i;j++)
//            printf("%d ",c[i][j]);
//         printf("\n");
//     }
}
struct Matrix{
	ll arr[N][N];
	void init()
	{
		memset(arr,0,sizeof(arr));
		for(int i=0;i<MAXN;i++)
			arr[i][i]=1;//初始化
	}
	void iinit()
	{
	    memset(arr,0,sizeof(arr));
	    arr[0][0]=2;
	    for(int i=1;i<=MAXN;i++)
            arr[0][i]=arr[1][i]=c[k][i-1];
        for(int j=2;j<=MAXN;j++)
            for(int i=2;i<=MAXN;i++)
            {
                arr[j][i+j-2]=c[k-j+1][i-2];
            }
//        for(int j=0;j<=MAXN;j++)
//        {
//            for(int i=0;i<=MAXN;i++)
//                printf("\t%lld ",arr[j][i]);
//            cout<<endl;
//
//        }
	}
	void show()
	{
        for(int j=0;j<=MAXN;j++)
        {
            for(int i=0;i<=MAXN;i++)
                printf("\t%lld ",arr[j][i]);
            cout<<endl;

        }
	}
}A;
Matrix mul(Matrix X,Matrix Y)// 矩阵乘法
{
	Matrix ans;
	for(int i=0;i<MAXN;i++)
		for(int j=0;j<MAXN;j++){
			ans.arr[i][j]=0;
			for(int k=0;k<MAXN;k++){
				ans.arr[i][j]+=X.arr[i][k]*Y.arr[k][j];
			ans.arr[i][j]%=MOD;
			}
		}
	return ans;
}
Matrix Q_pow(Matrix B,ll n)// 矩阵快速幂
{
	Matrix ans;
	ans.init();
	while(n)
	{
		if(n&1)
			ans=mul(ans,B);
		n>>=1;
		B=mul(B,B);
	}
	return ans;
}

int main()
{
    init_tab();
    scanf("%lld %d",&n,&k);
    {
        Matrix ans;
        if(n<=1)
        {
            printf("1\n");
            return 0;
        }
        ans.iinit();
        ans=Q_pow(ans,n-1);
        ll res=0;
        for(int i=0;i<=k;i++)
            res+=(ans.arr[0][i])%MOD;
        printf("%lld\n",res%MOD);
        //ans.show();
    }

    return 0;
}


posted @ 2017-08-12 10:30  Sizaif  阅读(142)  评论(0编辑  收藏  举报