Best Solver(根据公式推 通项) [类斐波那契]

版权声明:小白一个,欢迎各位指错。 https://blog.csdn.net/qq_36424540/article/details/82218252

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

没想到要找循环节,一开始想的欧拉降幂,后来发现自己是个傻子,无理数,和有理数。看到题解说是找循环节,这恐怕是解决巨长数列 某个位置上的数的有效办法。

构造+找循环节

#include<cstdio>
using namespace std;

#define rep(i,a,b) for(int i=a;i<b;i++)

typedef long long LL;

const int N=50000;

LL pow_mod(LL base,LL n,LL mod){
    LL ans=1;
    while(n){
        if(n&1)ans=ans*base%mod;
        base=base*base%mod;
        n>>=1;
    }
    return ans%mod;
}

/*
能不取模,就不要取
*/

int a[N];
int get_loop(LL mod){
    a[0]=10;if(a[0]>=mod)a[0]=a[0]%mod;
    a[1]=98;if(a[1]>=mod)a[1]=a[1]%mod;
    rep(i,2,N){
        a[i]=(10LL*a[i-1]-1LL*a[i-2]+mod)%mod;
        if(a[i-1]==a[0]&&a[i]==a[1]){
           return  i-1;
        }
        //printf("i:%d %lld\n",i,a[i]);
    }
}

int main(){
    int T;
    scanf("%d",&T);
    rep(kase,0,T){
       LL x,mod;
       scanf("%lld %lld",&x,&mod);
       int loop=get_loop(mod);

       printf("Case #%d: ",kase+1);

       int num=pow_mod(2LL,x,loop);
       //printf("loop:%lld num:%lld\n",loop,num);
       printf("%d\n",(a[num]-1+mod)%mod);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36424540/article/details/82218252
今日推荐