UPC4248【数论】数字迷阵
问题 J: 【数论】数字迷阵
时间限制: 1 Sec 内存限制: 128 MB提交: 11 解决: 10
[提交] [状态] [命题人:admin]
题目描述
小可可参观科学博物馆时,看到一件藏品,上面有密密麻麻的数字,如下所示:
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
发现一道很有意思的题目,根据题意,我们的任务重点放在了如何求解每一行的第一个数,而第二项的递推式子已经给出,后面的第j项,可以用矩阵快速幂直接求解。
打了个表观察第一列的数字,会发现每十三个数分别增加3,2,3,3,2,3,2,3,3,2,3,3,2,所以我们将这十三个数存下来就ok了。一道无从下手的题秒变水题。
AC代码
#include <bits/stdc++.h> typedef long long ll; using namespace std; ll mod; struct mat { ll a[2][2]; mat operator *(const mat &t)const { mat res; for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { res.a[i][j]=0; for(int k=0;k<2;k++) res.a[i][j]=(res.a[i][j]+a[i][k]*t.a[k][j]%mod)%mod; } } return res; } }; mat qpow(mat a,ll b) { mat ans; ans.a[0][0]=ans.a[1][1]=1; ans.a[0][1]=ans.a[1][0]=0; while(b) { if(b&1)ans=ans*a; a=a*a; b>>=1; } return ans; } int nb[14]={0,3,2,3,3,2,3,2,3,3,2,3,3,2}; ll a,b; int main() { ios::sync_with_stdio(false); cin.tie(0); ll i,j; cin>>i>>j>>mod; for(int i=1;i<=13;i++)nb[i]+=nb[i-1]; a=1+nb[13]*((i-1)/13)+nb[(i-1)%13]; b=a*2-i+1; mat A,B; A.a[0][0]=1; A.a[0][1]=1; A.a[1][0]=1; B.a[0][0]=b; B.a[1][0]=a; A=qpow(A,j-2)*B; printf("%lld\n",A.a[0][0]); return 0; }