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
题解
显然矩阵乘法,关键在于i^k。
我们知道(i+1)^k分解后系数为杨辉三角数,因此我们可以利用i^k,i^(k-1)……i^0推导出(i+1)^k……(i+1)^0
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<set>
#include<ctime>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#define mod 1000000007
#define ll long long
#define N 25
#define inf 0x7fffffff
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
ll n;
int k,ans[N][N],a[N][N],b[N][N],fac[N];
void mul(int a[N][N],int b[N][N],int c[N][N])
{
int tmp[N][N];
for (int i=1;i<=k;i++)
for (int j=1;j<=k;j++)
{
tmp[i][j]=0;
for (int x=1;x<=k;x++)
tmp[i][j]=(tmp[i][j]+(ll)a[i][x]*b[x][j]%mod)%mod;
}
for (int i=1;i<=k;i++)
for (int j=1;j<=k;j++)
c[i][j]=tmp[i][j];
}
int main()
{
scanf("%lld",&n);k=read()+1;n-=2;
fac[1]=1;
for (int i=2;i<=k;i++) fac[i]=fac[i-1]*2%mod;fac[k+1]=1;
a[1][1]=1;
for (int i=2;i<=k;i++)
for (int j=1;j<=i;j++)
a[i][j]=(a[i-1][j]+a[i-1][j-1])%mod;
k++;a[k][k-1]=1;a[k][k]=2;
for (int i=1;i<=k;i++)
for (int j=1;j<=k;j++) b[i][j]=a[i][j];
for (int i=1;i<=k;i++) ans[i][i]=1;
while (n)
{
if (n&1) mul(ans,a,ans);
n>>=1;
mul(a,a,a);
}
int ANS1=0;
for (int i=1;i<=k;i++) ANS1=(ANS1+(ll)fac[i]*ans[k][i]%mod)%mod;
mul(ans,b,ans);
int ANS2=0;
for (int i=1;i<=k;i++) ANS2=(ANS2+(ll)fac[i]*ans[k][i]%mod)%mod;
printf("%d",(ANS2-ANS1+mod)%mod);
return 0;
}