Description
热情好客的请森林中的朋友们吃饭,他的朋友被编号为 1~N,每个到来的朋友都会带给他一些礼物:。其中,第一个朋友会带给他 1 个,之后,每一个朋友到来以后,都会带给他之前所有人带来的礼物个数再加他的编号的 K 次方那么多个。所以,假设 K=2,前几位朋友带来的礼物个数分别是1,5,15,37,83假设 K=3,前几位朋友带来的礼物个数分别是:1,9,37,111现在,好奇自己到底能收到第 N 个朋友多少礼物,因此拜托于你了。已知 N,K请输出第 N 个朋友送的礼物个数 mod1000000007。
PDF题面:www.lydsy.com/JudgeOnline/upload/gift.pdf
Input
第一行,两个整数 N,K N≤10^18,K≤10
Output
一个整数,表示第 N 个朋友送的礼物个数 mod1000000007。
Sample Input
4 2
Sample Output
37
题目分析
设为答案,
那么就有:
因为N很大 所以我们要考虑矩乘
关键是怎么从转移到
不怕 我们有二项式定理:
据此 我们可以得到转移矩阵如下:
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
int n,k;
long long m,mod=1000000007,c[20][20];
struct your
{
long long x[20][20];
your() { memset(x,0,sizeof x); }
friend your operator*(your x,your y)
{
your z;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int l=1;l<=n;l++)
z.x[i][j]=(z.x[i][j]+x.x[i][l]*y.x[l][j]%mod)%mod;
return z;
}
}A,B;
void ksm(long long y)
{
while(y)
{
if(y&1) A=A*B;
y>>=1,B=B*B;
}
}
void init()
{
c[0][0]=1;
for(int i=1;i<=10;i++)
{
c[i][0]=1;
for(int j=1;j<=i;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
A.x[1][1]=A.x[1][2]=1;
for(int i=0;i<=k;i++) A.x[1][i+3]=1;
B.x[2][1]=1,B.x[2][2]=2;
for(int i=0;i<=k;i++) B.x[i+3][1]=B.x[i+3][2]=c[k][i];
for(int i=0;i<=k;i++)
for(int j=0;j<=i;j++) B.x[j+3][i+3]=c[i][j];
}
int main()
{
scanf("%lld%d",&m,&k),n=3+k;
init(),ksm(m-1);
printf("%lld",A.x[1][1]);
return 0;
}