首先对于S(n),可以写一个矩阵,用矩阵快速幂求解
S(n) | 1 1 1 | S(n-1)
f(n) | 0 1 1 | f(n-1)
f(n-1) | 0 1 0 | f(n-2)
求出来计算出L=S(n)%m之后,构造题目中要求的矩阵,找规律后发现,可以构造成以下最简单的形式
当L=0或者L为奇数时为No,L为偶数时Yes,例如L=6时
0 1 1 1 1 1
-1 0 1 1 1 1
-1 -1 0 1 1 1
-1 -1 -1 1 1 1
-1 -1 -1 -1 1 1
-1 -1 -1 -1 -1 1
对角线前一半为0,后一半为1,上三角为1,下三角为-1
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
ll MOD;
const int N=3;
struct node
{
ll a[10][10];
};
node shu,ans,mp;
//shu是输入的矩阵,ans是所求答案
node matrix(node x,node y)
{
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++){
mp.a[i][j]=0;
for(int p=1;p<=N;p++)
mp.a[i][j]=(mp.a[i][j]+(x.a[i][p]*y.a[p][j])%MOD+MOD)%MOD;
//矩阵乘法
}
return mp;
}
void work(ll k)
{//矩阵快速幂
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
ans.a[i][j]=0;
for(int i=1;i<=N;i++) ans.a[i][i]=1;
node t=shu;
while(k){
if(k&1)
ans=matrix(ans,t);
k>>=1;
t=matrix(t,t);
}
}
ll n,m;
void prt(int n)
{
int a[205][205];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(j<i) a[i][j]=-1;
else a[i][j]=1;
for(int i=0;i<n/2;i++)
a[i][i]=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n-1;j++)
printf("%d ",a[i][j]);
printf("%d\n",a[i][n-1]);
}
}
int main()
{
int T,kase=0;
scanf("%d",&T);
while(T--)
{
scanf("%I64d%I64d",&n,&m);
MOD=m;
printf("Case %d: ",++kase);
ll l;
if(n==2)
{
l=2%m;
}
else
{
memset(shu.a,0,sizeof(shu.a));
shu.a[1][1]=shu.a[1][2]=shu.a[1][3]=1;
shu.a[2][2]=shu.a[2][3]=shu.a[3][2]=1;
work(n-2);
l=(2*ans.a[1][1]+ans.a[1][2]+ans.a[1][3])%MOD;
}
if(l&1||l==0) printf("No\n");
else
{
printf("Yes\n");
prt(l);
}
}
return 0;
}