矩阵快速幂
矩阵快速幂一般是为了求解递推问题
eg:菲波那切数列
2. 小澳的 坐标系
(coordinate.cpp/c/pas )
【题目描述】
小澳者表也,数学者景也,表动则景随矣。
小澳不喜欢数学,可数学却待小澳如初恋,小澳睡觉的时候也不放过。
小澳的梦境中出现了一个平面直角坐标系,自原点,向四方无限延伸。
小澳在坐标系的 原点,他可以 向上、向左或者向右走。他可以走 n 步, 但不能经过相同的点。
小澳想知道他有多少种走法。
【输入格式】
输入文件名为 coordinate.in。
输入文件仅第一行一个正整数 n,表示小澳可以走的步数。
【输出格式】
输出文件名为 coordinate.out。
输出文件共一行,输出一个正整数,表示答案(对 10^9+7 取模)。
【输入输出样例 1 】
in:
2
out:
7
【输入输出样例 1 说明】
从(0,0)出发走 2 步,共 7 种走法:
(0,0)->(0,1)->(0,2)
(0,0)->(0,1)->(1,1)
(0,0)->(0,1)->(-1,1)
(0,0)->(1,0)->(2,0)
(0,0)->(1,0)->(1,1)
(0,0)->(-1,0)->(-2,0)
(0,0)->(-1,0)->(-1,1)
【输入输出样例 2 】
in:
3
out:
17
【数据规模与约定 】
测试点编号 n
1~2 n<=10
3~4 n<=100
5~6 n<=1000
7~8 n<=10^6
9~10 n<=10^9
Solution:
做这题的时候先写了一个走迷宫的暴力DFS,找到递推公式
//DFS暴力
#include<cstdio>
#define LL long long
#define mod 100000
using namespace std;
int n,cnt;
int map[2002][2009];
int u[3]={0,1,0},v[3]={1,0,-1};
bool inmap(int a,int b){
return a>=1 && a<=n+1 && b>=1 && b<=2*n+1;
}
void DFS(int x,int y,int t){
int i;
if(t==n){
cnt++;
if(cnt==mod) cnt=0;
return;
}
for(i=0;i<3;i++){
int xx=x+u[i],yy=y+v[i];
if(!map[xx][yy] && inmap(xx,yy)){
map[xx][yy]=1;
DFS(xx,yy,t+1);
map[xx][yy]=0;
}
}
}
int main(){
freopen("coordinate.in","r",stdin);
freopen("coordinate.out","w",stdout);
scanf("%d",&n);
map[1][n+1]=1;
DFS(1,n+1,0);
printf("%d",cnt);
return 0;
}
十以内可以解决了(20分)
然后将1~10内的解输出来找到递推关系
矩阵快速幂之所以要用,是因为它确实求递推式的时候很快
一般递推:
//SLOW
#include<cstdio>
#define LL long long
#define mod 1000000007
using namespace std;
int n;
void solve(){
if(n==1) {
printf("3\n");
return;
}
if(n==2){
printf("7\n");
return;
}
LL f1=3,f2=7,f3;
int i;
for(i=3;i<=n;i++){
f3=2*f2+f1;
f3%=mod;
f1=f2;f2=f3;
}
printf("%I64d",f3%mod);
}
int main(){
freopen("coordinate.in","r",stdin);
freopen("coordinate.out","w",stdout);
scanf("%d",&n);
solve();
return 0;
}
矩阵快速幂:
//FAST
#include<cstdio>
#define LL long long
#define mod 1000000007
int n;
struct M{
LL map[3][3];
};
M s;
M work(M x,M y){
int i,j,k;
M ans;
ans.map[1][1]=ans.map[1][2]=ans.map[2][1]=ans.map[2][2]=0;
for(i=1;i<=2;i++){
for(j=1;j<=2;j++){
for(k=1;k<=2;k++){
ans.map[i][j]+=x.map[i][k]*y.map[k][j];
}
ans.map[i][j]%=mod;
}
}
return ans;
}
void solve(){
M tmp;
n-=2;
tmp.map[1][1]=tmp.map[0][2]=0;tmp.map[1][2]=1;tmp.map[2][1]=1;tmp.map[2][2]=2;
while(n){
if(n&1){
s=work(tmp,s);
}
tmp=work(tmp,tmp);
n>>=1;
}
printf("%d",s.map[2][1]%mod);
}
int main(){
freopen("coordinate.in","r",stdin);
freopen("coordinate.out","w",stdout);
scanf("%d",&n);
if(n==1){
printf("3\n");return 0;
}
if(n==2){
printf("7\n");return 0;
}
s.map[1][1]=3;s.map[2][1]=7;
solve();
return 0;
}