#题目
Best Solver
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 1141 Accepted Submission(s): 655
Problem Description
The so-called best problem solver can easily solve this problem, with his/her childhood sweetheart.
It is known that y=(5+26√)1+2x.
For a given integer x (0≤x<232) and a given prime number M (M≤46337), print [y]%M. ([y] means the integer part of y)
Input
An integer T (1<T≤1000), indicating there are T test cases.
Following are T lines, each containing two integers x and M, as introduced above.
Output
The output contains exactly T lines.
Each line contains an integer representing [y]%M.
Sample Input
7
0 46337
1 46337
3 46337
1 46337
21 46337
321 46337
4321 46337
Sample Output
Case #1: 97
Case #2: 969
Case #3: 16537
Case #4: 969
Case #5: 40453
Case #6: 10211
Case #7: 17947
#分析
这显然是道快速幂的题目,不过我们首先需求出取整后的表达式,因为小数无法取模。
然后由于(5+sqrt(24))^n+(5-sqrt(24))^n一定为整数,且(5-sqrt(24))^n<1,得出(5+sqrt(24))^n的整数部分为
(5+sqrt(24))^n+(5-sqrt(24))^n-1,然后通过特征方程的方法将上面的式子转化为递推式(广义Fabonacci数列),又由于广义Fabonacci数列取模拥有循环节(周期性,详见博客https://blog.csdn.net/ACdreamers/article/details/25616461),求出循环节,再对1+2^x用快速幂进行分解,便可得出答案。
对于化为递推式:
类比于Fabonacci数列,F[n]=F[n-1]+F[n-2]形式,可以化为
所有的F[n]=p*F[n-1]+q*F[n-2]形式都能与A*x^n+B*y^n形式通过特征方程相互转换
(参考https://blog.csdn.net/happykocola/article/details/73933314,https://blog.csdn.net/hanchengxi/article/details/17550429)
对于这道题,F[n]=(5+sqrt(24))^n+(5-sqrt(24))^n,可以求出递推式F[n]=10*F[n-1]-F[n-2]。
#AC码
#include <iostream>
#include <string.h>
using namespace std;
int T;
int M;
long long x;
int f[47338]; //递推式取模后的值,也就是答案+1
//这里的数组大小详见推荐的博客,循环节的大小,这个值并非准确的值,理论上应该取M^2,不过M^2超内存
//寻找循环节长度,同时记录值
int f_cir()
{
f[1]=10%M;
f[2]=98%M;
int i=3;
while(1)
{
f[i]=(10*f[i-1]-f[i-2]+M)%M; //加M是因为10*f[i-1]-f[i-2]可能为负
if(f[i]==f[2]&&f[i-1]==f[1])
return i-2;
i++;
}
}
int f_ans(int p)//p为周期,现在需求出(1+2^x)%p的值(等于2^x%p+1),对2^x%p使用快速幂
{
int ans=1;
int a=2;
while(x)
{
if(x&1)
ans=(ans*a)%p;
a=(a*a)%p;
x>>=1;
}
return (f[ans+1]-1)%M; //答案为f[n]-1
}
int main()
{
//freopen("5451.txt","r",stdin);
cin>>T;
for(int t=1;t<=T;t++)
{
cin>>x>>M;
int per=f_cir();
cout<<"Case #"<<t<<": ";
cout<<f_ans(per)<<endl;
}
}