传送门
题意:计算此式子S(n)的第n项
分析:列出S(n)的前几项,就会发现S(n)与fib数列的关系:
S(0)=0=f(0)
S(1)=1=f(2)
S(2)=3=f(4)
S(3)=8=f(6)
......
S(n)= =f(2n)
然后就可以直接套模板了;
typedef long long ll;
const int maxn=2;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}return x*f;
}
int main()
{
int t=read();while (t--)
{
ll f[maxn][maxn]={3,-1,1,0},mxt[maxn][maxn]={1,0,0,1};
ll n=read(),p=read();
if(n==0){
printf("%lld\n",0);
continue;
}
if(n==1){printf("%lld\n",1);
continue;}
n-=2;
while (n)
{
if(n&1)
{
ll res[maxn][maxn]={0};
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
for(int k=0;k<maxn;k++)
res[i][j]+=f[i][k]*mxt[k][j]%p,res[i][j]%=p;
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
mxt[i][j]=res[i][j];
}
ll res[maxn][maxn]={0};
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
for(int k=0;k<maxn;k++)
res[i][j]+=f[i][k]*f[k][j]%p,res[i][j]%=p;
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
f[i][j]=res[i][j];
n>>=1;
}
ll ans=3*mxt[0][0]-mxt[0][1];
printf("%lld\n",ans);
}
return 0;
}
其实这还有另外一种推导式
S(n)=3*S(n-1)-S(n-2);