思路:S(n) = S(n-1) + f(n),通过构造矩阵可以求出S(n),主要问题就是构造一个S(n) * S(n)的矩阵满足条件。
自己写一写就能找出构造方法,因为矩阵只包括0,1,-1,那么一个n*n的矩阵,每一行的sum在-n到n之间,又因为-n和n不能同时存在,所以我们可以让每一行的和在-n到n-1之间,一共2*n个数,刚好对应n行,n列,每一行每一列的sum都不相同,然后构造就行了。
#include<cstdio>
#include<cstring>
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
typedef long long LL;
struct Mutrix{
LL a[3][3];
Mutrix(){
memset(a, 0, sizeof a);
}
};
Mutrix A, B;
LL m;
void init(){
A.a[0][0] = 1, A.a[0][1] = 1, A.a[0][2] = 1;
B.a[0][0] = 1;
B.a[1][2] = 1;
B.a[2][0] = 1, B.a[2][1] = 1, B.a[2][2] = 1;
}
Mutrix mul(Mutrix p1, Mutrix p2){
Mutrix s;
for(int i = 0; i < 3; ++i){
for(int k = 0; k < 3; ++k){
for(int j = 0; j < 3; ++j){
s.a[i][j] += p1.a[i][k] * p2.a[k][j] % m;
s.a[i][j] %= m;
}
}
}
return s;
}
Mutrix quick_mod(Mutrix x, LL y){
Mutrix ret;
for(int i = 0; i < 3; ++i) ret.a[i][i] = 1;
while(y){
if(y & 1) ret = mul(ret, x);
x = mul(x, x);
y >>= 1;
}
return ret;
}
int a[220][220];
int main(){
LL n;
int kase = 0, T;
scanf("%d", &T);
while(T--){
scanf("%I64d%I64d", &n, &m);
init();
LL w = mul(A, quick_mod(B, n - 1)).a[0][0] % m;
printf("Case %d: ", ++kase);
if(w == 0 || w & 1) {
printf("No\n");
continue;
}
else printf("Yes\n");
memset(a, 0, sizeof a);
for(int i = 0; i < w; ++i){
for(int j = 0; j < w; ++j){
if(i < w / 2){
if(j >= i) a[i][j] = 1;
}
else{
if(j < i) a[i][j] = -1;
}
}
}
for(int i = 0; i < w; ++i){
for(int j = 0; j < w; ++j){
printf("%d ", a[i][j]);
}
printf("\n");
}
}
return 0;
}