Fibonacci Check-up
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1356 Accepted Submission(s): 778
Problem Description
Every ALPC has his own alpc-number just like alpc12, alpc55, alpc62 etc.
As more and more fresh man join us. How to number them? And how to avoid their alpc-number conflicted?
Of course, we can number them one by one, but that’s too bored! So ALPCs use another method called Fibonacci Check-up in spite of collision.
First you should multiply all digit of your studying number to get a number n (maybe huge).
Then use Fibonacci Check-up!
Fibonacci sequence is well-known to everyone. People define Fibonacci sequence as follows: F(0) = 0, F(1) = 1. F(n) = F(n-1) + F(n-2), n>=2. It’s easy for us to calculate F(n) mod m.
But in this method we make the problem has more challenge. We calculate the formula
, is the combination number. The answer mod m (the total number of alpc team members) is just your alpc-number.
As more and more fresh man join us. How to number them? And how to avoid their alpc-number conflicted?
Of course, we can number them one by one, but that’s too bored! So ALPCs use another method called Fibonacci Check-up in spite of collision.
First you should multiply all digit of your studying number to get a number n (maybe huge).
Then use Fibonacci Check-up!
Fibonacci sequence is well-known to everyone. People define Fibonacci sequence as follows: F(0) = 0, F(1) = 1. F(n) = F(n-1) + F(n-2), n>=2. It’s easy for us to calculate F(n) mod m.
But in this method we make the problem has more challenge. We calculate the formula

Input
First line is the testcase T.
Following T lines, each line is two integers n, m ( 0<= n <= 10^9, 1 <= m <= 30000 )
Following T lines, each line is two integers n, m ( 0<= n <= 10^9, 1 <= m <= 30000 )
Output
Output the alpc-number.
Sample Input
2 1 30000 2 30000
Sample Output
1 3
分析:
先暴力打表找出规律,得出递推式为:F(n) = 3*F(n-1) - F(n-2)
由于N很大,线性时间会超时,要优化到 log(N),所以将递推公式变为矩阵,由矩阵快速幂求解即可。
形如: F(n) = a*F(n-1) + b*F(n-2)的式子,可以转化为:
a b
1 0
形式的矩阵。
代码:
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long int ll;
/**暴力打表找规律
int arr[10];
int C(int n,int m){
int ans = 1;
for(int i=0; i<m; i++)
ans *= (n-i);
for(int i=1; i<=m; i++)
ans /= i;
return ans;
}
void make_list(){
int Fac[10];
Fac[0] = 0;
Fac[1] = Fac[2] = 1;
for(int i=3; i<10; i++)
Fac[i] = Fac[i-1]+Fac[i-2];
arr[0] = 0;
for(int i=1; i<10; i++){
for(int j=0; j<=i; j++)
arr[i] += C(i,j)*Fac[j];
}
for(int i=0; i<10; i++)
cout << arr[i] << endl;
} */
int N,M;
struct matrix{
int a[2][2];
matrix operator*(const matrix& tmp){
matrix ans;
memset(ans.a,0,sizeof(ans.a));
for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
for(int k=0; k<2; k++)
ans.a[i][j] = (ans.a[i][j] + a[i][k]*tmp.a[k][j])%M;
return ans;
}
};
matrix quick_pow(matrix a,int n){
matrix ans;
ans.a[0][0] = ans.a[1][1] = 1;
ans.a[0][1] = ans.a[1][0] = 0;
while(n){
if(n%2)
ans = ans*a;
a = a*a;
n /= 2;
}
return ans;
}
int main(){
//make_list();
int T;
scanf("%d",&T);
matrix ans;
while(T--){
ans.a[0][0] = 3;
ans.a[0][1] = -1;
ans.a[1][0] = 1;
ans.a[1][1] = 0;
scanf("%d %d",&N,&M);
if(N==0){
printf("0\n");
continue;
}
ans = quick_pow(ans,N-1);
printf("%d\n",(ans.a[0][0]+M)%M);
}
return 0;
}