题意:

给定一个\(k\)维的\(n^k\)的超立方体,超立方体的元素\(A(i1,i2,...,ik)\)的值为\(f(i1+i2+...+ik-k+1)\),f为斐波那契数列

求该超立方体的所有元素和

\(1 \le n,k \le 10^9\)

输入样例

3
2 2
4 1
1 3

输出样例

5
7
1

题解

自己好长时间没写题解了,自己好懒啊。
假如k=1,那么就是答案就是斐波那契数列的前缀和。
这里有一个神奇的结论 :设\(f[i]\)为斐波那契数列的第\(i\)项,则\(\displaystyle \sum_{i=1}^{n}f[i]=f[n+2]-f[2]\)
我们用矩阵快速幂就能解决啦。
假如k<=100,我们就需要用到一个神奇的结论了:当我们做完一维后,可以把这维看成成一个点,权值是这维的和。
我们先来考虑只有两维的情况,我们求的就是\(\displaystyle \sum_{i=1}^{n}(\sum_{j=1}^{n}f[i+j])\),我们发现我们求完了一维后,将这一维压缩成前缀和后,我们会面临相同的子问题。推广到k维依然适合,所以我们可以用k次快速幂来解决。
假如k更大,我们可以考虑维之间的转化,假如我们求出了转移到下一维的矩阵B,我们用初始矩阵\(A\)乘上\(B^k\)就能求出来答案。
那B怎么求呢?我们发现维度的转换只用求出来这一维的前缀和就行了,而刚刚的\(\displaystyle \sum_{i=1}^{n}f[i]=f[n+2]-f[2]\)在更高维上显然依然适用,将公式套到矩阵上就可以啦。

#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
const int mod=1e9+7;
LL n,k,T;
struct ju
{
	LL v[3][3];
	friend ju operator *(const ju &a,const ju &b)
	{
		ju c;memset(c.v,0,sizeof(c.v));
		for(int i=1;i<=2;++i)
			for(int j=1;j<=2;++j)
				for(int k=1;k<=2;++k)
					(c.v[i][j]+=a.v[i][k]*b.v[k][j])%=mod;
		return c;
	}
	friend ju operator -(const ju &a,const ju &b)
	{
		ju c;memset(c.v,0,sizeof(c.v));
		for(int i=1;i<=2;++i)
			for(int j=1;j<=2;++j)
				c.v[i][j]=(a.v[i][j]-b.v[i][j]+mod)%mod;
		return c;
	}
}A,B;
void YYCH()
{
	A.v[1][1]=1;A.v[1][2]=0;
	B.v[1][1]=1;B.v[1][2]=1;B.v[2][1]=1;
}
ju ksm(ju a,LL b)
{
	ju res;memset(res.v,0,sizeof(res.v));
	res.v[1][1]=res.v[2][2]=1;
	for(;b;b>>=1,a=a*a)
		if(b&1)res=res*a;
	return res;
}
int main()
{
	YYCH();
	cin>>T;
	while(T--)
	{
		scanf("%lld%lld",&n,&k);
		printf("%lld\n",(A*ksm(ksm(B,n+1)-B,k)).v[1][1]);
	}
	return 0;
}