Best Solver HDU - 5451 (共轭构造)

The so-called best problem solver can easily solve this problem, with his/her childhood sweetheart. 

It is known that y=(5+26–√)1+2xy=(5+26)1+2x. 
For a given integer x (0≤x<232)x (0≤x<232) and a given prime number M (M≤46337)M (M≤46337), print [y]%M[y]%M. ([y][y] means the integer part of yy) 

Input

An integer T (1<T≤1000)T (1<T≤1000), indicating there are TT test cases. 
Following are TT lines, each containing two integers xx and MM, as introduced above.

Output

The output contains exactly TT lines. 
Each line contains an integer representing [y]%M[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

 

思路:遇到带根号的式子,想到共轭构造斐波那契函数。详见:戳这里。因此我们构造此斐波那契额数列为

,带入公示知:

易知,an是整数,由于所要求的结果是只取y的整数部分,而该式的后一部分是小于1的小数。因此若我们相求y的整数部分,只需求an -1即可。  

由于斐波那契额数列取于一个数  是一定遵循循环节的。因此我们找到循环姐,再求an即可

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include<map>
#include<cstring>
#define ll long long
using namespace std;
ll rm[1008611],a[1008611];
ll x,m;
ll q_pow(ll b,ll mod){
    ll ans = 1;
    ll num = 2;
    while(b){
        if(b & 1)
            ans = ans * num % mod;
        b >>= 1;
        num = num * num % mod;
    }
    return ans;
}
ll solve(){
    ll n,ans;
    n=(q_pow(x, rm[m])+1)%rm[m];
    a[0]=2%m;
    a[1]=10%m;
    for(ll i=2;i<=n;i++){
        a[i]=(10*a[i-1]-a[i-2]+m)%m;
    }
    ans=(a[n]-1+m)%m;
    return ans;
}
void init(){
    if(rm[m]!=0)return;//若之前找过这个循环节,则直接return
        a[0]=2%m;
        a[1]=10%m;
        for(int i=2;;i++){
            a[i]=(10*a[i-1]-a[i-2]+m)%m;
            if(a[i-1]==a[0]&&a[i]==a[1]){
                rm[m]=i-1;
                break;
            }
    }
}
int main(){
    ll t,ca=1;
    cin>>t;
    memset(rm, 0, sizeof(rm));
    while(t--){
        cin>>x>>m;
        init();//找循环节rm
        ll ans=solve();
        printf("Case #%lld: %lld\n",ca++,ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值