5451 Best Solver

本文介绍了一种解决特定数学问题的方法,利用快速幂运算和递推式来高效计算复杂表达式的取模结果。通过分析表达式的特性,将其转换为广义斐波那契数列的形式,并利用该数列的周期性特点找到解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#题目

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.youkuaiyun.com/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.youkuaiyun.com/happykocola/article/details/73933314https://blog.youkuaiyun.com/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;
    }
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值