数字迷阵(矩阵快速幂+结论题)
题目描述
小可可参观科学博物馆时,看到一件藏品,上面有密密麻麻的数字,如下所示:
1 2 3 5 8 13 21 34 55 89 144 …
4 7 11 18 29 47 76 123 199 322 521 …
6 10 16 26 42 63 110 178 288 466 754 …
9 15 24 39 63 102 165 267 432 699 1131 …
12 20 32 52 84 136 220 356 576 932 1508 …
14 23 37 60 97 157 254 411 665 1076 1741 …
17 28 45 73 118 191 309 500 809 1309 2118 …
19 31 50 81 131 212 343 555 898 1453 2351 …
22 36 58 94 152 246 398 644 1042 1686 2728 …
25 41 66 107 173 280 453 733 1186 1919 3105 …
27 44 71 115 186 301 487 788 1275 2063 3338 …
…
仔细一分析,发现还挺有规律。
原来,第一行是Fibonacci数列。即,该行中除了第一个和第二个数分别为1和2之外,其他数都是其左侧相邻的两个数之和。
其后各行也类似于Fibonacci数列。只是第i行的第一个数是前 行中未出现的最小正整数,而其第二个数与该行第一个数以及所在行的编号相关,即A[i,2]=A[i,1]*2-(i-1) 。如在第一行中未出现的最小正整数为4,前三行中未出现的最小正整数为9。故第二行以4和7开头,而第四行以9和15开头。
小可可高兴地把这个发现告诉了爷爷。爷爷问道:你能否一口报出第i行、第j列的那个数对m取模的结果是多少呢?
聪明的小可可通过心算就能知道答案。你是否能编写程序求解呢?
1 2 3 5 8 13 21 34 55 89 144 …
4 7 11 18 29 47 76 123 199 322 521 …
6 10 16 26 42 63 110 178 288 466 754 …
9 15 24 39 63 102 165 267 432 699 1131 …
12 20 32 52 84 136 220 356 576 932 1508 …
14 23 37 60 97 157 254 411 665 1076 1741 …
17 28 45 73 118 191 309 500 809 1309 2118 …
19 31 50 81 131 212 343 555 898 1453 2351 …
22 36 58 94 152 246 398 644 1042 1686 2728 …
25 41 66 107 173 280 453 733 1186 1919 3105 …
27 44 71 115 186 301 487 788 1275 2063 3338 …
…
仔细一分析,发现还挺有规律。
原来,第一行是Fibonacci数列。即,该行中除了第一个和第二个数分别为1和2之外,其他数都是其左侧相邻的两个数之和。
其后各行也类似于Fibonacci数列。只是第i行的第一个数是前 行中未出现的最小正整数,而其第二个数与该行第一个数以及所在行的编号相关,即A[i,2]=A[i,1]*2-(i-1) 。如在第一行中未出现的最小正整数为4,前三行中未出现的最小正整数为9。故第二行以4和7开头,而第四行以9和15开头。
小可可高兴地把这个发现告诉了爷爷。爷爷问道:你能否一口报出第i行、第j列的那个数对m取模的结果是多少呢?
聪明的小可可通过心算就能知道答案。你是否能编写程序求解呢?
输入
每行有三个分别用一个空格隔开的正整数,分别是i、j和m。其中,i, j<=1000000000 ,2<=m<=10000 。
输出
每行输出对应的第i行、第j列的那个正整数对m取模的结果。
样例输入
复制样例数据
1 2 99
样例输出
2
ps:第一列之差3 2 3 3 2 3 2 3 3 2 ,然后就有人推出结论,每一行第一个数为,i-1+i*((1+sqrt(5))/2; 神奇!
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct mat{
ll m[2][2];
}unit;
ll m,a,b;
mat operator*(mat a,mat b){
mat ret;
memset (ret.m,0, sizeof (ret.m));
for(int i=0;i<2;i++) {
for(int j=0;j<2;j++) {
for(int k=0;k<2;k++) {
ret.m[i][j]=(ret.m[i][j]+a.m[i][k]*b.m[k][j]%m)%m;
}
}
}
return ret;
}
void init()
{
for(int i=0;i<2;i++) unit.m[i][i]=1;
return;
}
mat pow_mat(mat a,ll n){
mat ret=unit;
while (n){
if(n&1) {
ret=ret*a;
}
n>>=1;
a=a*a;
}
return ret;
}
int main()
{
init ();
scanf ("%lld%lld%lld",&a,&b,&m);
ll f1=a-1+a*(sqrt (5)+1)/2;
ll f2=f1*2-(a-1);
mat A={
1,1,
1,0
};
mat B={
f2,f1,
0,0
};
mat C=pow_mat (A,b-1);
C=B*C;
cout<<C.m[0][1]<<endl;
return 0;
}