Construct a Matrix
1. The matrix is a S(n)×S(n) matrix;
2. S(n) is the sum of the first n Fibonacci numbers modulus m, that is S(n) = (F1 + F2 + … + Fn) % m;
3. The matrix contains only three kinds of integers ‘0’, ‘1’ or ‘-1’;
4. The sum of each row and each column in the matrix are all different.
Here, the Fibonacci numbers are the numbers in the following sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …
By definition, the first two Fibonacci numbers are 1 and 1, and each remaining number is the sum of the previous two.
In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation Fn = Fn-1 + Fn-2, with seed values F1 = F2 = 1.
Given two integers n and m, your task is to construct the matrix.
Input
Output
Sample Input
2
2 3
5 2
Sample Output
Case 1: Yes
-1 1
0 1
Case 2: No
上一篇是poj3070 -- 赤果果的矩阵快速幂
[fn+1 fn] [1 1]^n [fn fn-1]=[1 0] .... --神奇(★精华在这) 模拟一下就发现其实是有道理的每次乘以{(1,1)(1,0)}矩阵得到{(fn+1+fn,fn+1),(fn+1,fn)}发现每次向后移动了一个斐波那契数列 但本题要的是f1~fn的和,故加一维 [1 1 0]^(n-2) [1 0 0] 设矩阵A=[1 1 1] 的最底下一行A(2,1)+A(2,2)+2*A(2,2)=斐波那契数列的前n项和 #include<iostream> #include<cstdio> using namespace std; #define width 3 int n,a[width][width],b[width][width],m; void mul(int a[width][width],int b[width][width],int ans[width][width]) { int t[width][width],i,j; for(i=0;i<width;i++) for(j=0;j<width;j++) { t[i][j]=0; for(int k=0;k<width;k++) t[i][j]=(t[i][j]+a[i][k]*b[k][j])%m; } for(i=0;i<width;i++) for( j=0;j<width;j++) ans[i][j]=t[i][j]; } void p(int t[width][width]) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) printf("%d ", t[i][j]); printf("\n"); } } int main() { int t,c=1,i,j,rl; //freopen("in.h","r",stdin); scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); a[0][0]=a[0][1]=a[1][0]=1;a[1][1]=a[1][2]=a[0][2]=0; a[2][0]=a[2][1]=a[2][2]=1; memset(b,0,sizeof(b)); b[0][0]=b[1][1]=b[2][2]=1; //n++; n-=2; if(n>2) { n-=2; while(n) { if(n&1)mul(a,b,b); n>>=1; mul(a,a,a); } rl=(b[2][0]+b[2][1]+b[2][2]*2)%m; //cout<<rl<<endl; //p(b); } else rl=n%m; if((rl&1)==0 && rl>0 ) { printf("Case %d: Yes\n",c++); for(i=0;i<rl-1;i++)printf("1 "); printf("1\n"); for(i=1;i<rl;i++) { for(j=0;j<rl-i-1;j++)printf("1 "); if(i<rl/2)printf("1 "); else printf("0 "); for(j++;j<rl-1;j++)printf("-1 "); printf("-1\n"); } } else printf("Case %d: No\n",c++); } return 0; }
还无聊的写了个dfs()暴力求构造的种树,当然跑起来很费时间
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> #include<map> using namespace std; //typedef long long ll; #define MAXN 50 int t, n, m; map<int,int> vis; int next[MAXN],s1[MAXN],s2[MAXN]; int a[55][55],d=4,flag; int judge() { int i,j,ans=0; memset(s2,0,sizeof(s2)); memset(s1,0,sizeof(s1)); vis.clear(); for(i=1;i<=d;i++) { for(j=1;j<=d;j++) { s1[j]+=a[i][j];//列 s2[i]+=a[i][j]; } if(vis[s2[i]])return 0; vis[s2[i]]=1; //cout<<s2[i]<<" "; } for(i=1;i<=d;i++) { if(vis[s1[i]])return 0; vis[s1[i]]=1; //cout<<s1[i]<<" "; } //cout<<endl; return 1; } void dfs(int x,int y) { int i,j,k; if(y==d+1) { x++,y=0; if(x==d+1) { if(judge()) //if(flag==170) { //judge(); for(j=1;j<=d;j++) { for(k=1;k<=d;k++) cout<<a[j][k]<<" ";cout<<endl; } cout<<"种 "<<flag++<<endl; cout<<endl; } //flag++; return ; } } for(i=-1;i<=1;i++) { a[x][y]=i; dfs(x,y+1); } } int main() { int i, j; while(scanf("%d", &t)) { flag=1; dfs(1,1); } return 0; }