[JZOJ5736]斐波那契

gcd(afn+bfn+1,cfn+dfn+1) gcd ( a f n + b f n + 1 , c f n + d f n + 1 )
首先有几个简单的性质:
gcd(fx,fy)=fgcd(x,y) gcd ( f x , f y ) = f g c d ( x , y )
gcd(a,b)=gcd(akb,b) gcd ( a , b ) = gcd ( a − k b , b )
gcd(b,c)=1 gcd ( b , c ) = 1 ,那么 gcd(ab,c)=gcd(a,c) gcd ( a b , c ) = gcd ( a , c )
先通过辗转相除把 c c 消成 0 0 ,那么只要考虑 gcd(afn+bfn+1,dfn+1) gcd ( a ′ f n + b ′ f n + 1 , d ′ f n + 1 )
首先通过矩阵乘法我们可以求出 fn f n 在模一个常数 a a 下的值,那么就可以求 gcd(fn,a)=gcd(fn%a,a) gcd ( f n , a ) = gcd ( f n % a , a )
g=gcd(fn+1,a) g = gcd ( f n + 1 , a ′ ) ,那么答案就等于 ggcd(afn+bfn+1g,dfn+1g) g ⋅ gcd ( a ′ f n + b ′ f n + 1 g , d ′ f n + 1 g )
因为 gcd(afn+bfn+1g,fn+1g)=1 gcd ( a ′ f n + b ′ f n + 1 g , f n + 1 g ) = 1 ,那么答案就是 ggcd(afn+bfn+1g,d)=gcd(afn+bfn+1,gd) g ⋅ gcd ( a ′ f n + b ′ f n + 1 g , d ′ ) = gcd ( a ′ f n + b ′ f n + 1 , g ⋅ d ′ )
只需要求出 gcd(fn,gd) gcd ( f n , g ⋅ d ) gcd(fn+1,gd) gcd ( f n + 1 , g ⋅ d ) 即可。
注意特判 a=0 a ′ = 0 d=0 d ′ = 0 的情况。复杂度 O(T23logn) O ( T ⋅ 2 3 log ⁡ n )
代码:

#include
#include
#include
#define ll long long
#define up(x,y) (x=(x+(y))%mod)
#define abs(x) (x<0?-(x):x)
using namespace std;
const int MOD=998244353;
int mod;
ll gcd(ll a,ll b)
{
    if(!b) return a;
    return gcd(b,a%b);
}
ll f[12];
struct matrix
{
    int h,w;
    ll a[2][2];
    matrix(int hx,int wx){memset(a,0,sizeof(a));h=hx;w=wx;}
    matrix operator *(matrix b)
    {
        matrix re(h,b.w);
        for(int i=0;ifor(int j=0;jfor(int k=0;k*b.a[k][j]);
        return re;          
    }
}mf(2,2);
matrix ksm(matrix a,ll b)
{
    matrix re(a.h,a.w);
    for(int i=0;i1;
    for(;b;b>>=1)
    {   
        if(b&1) re=re*a;
        a=a*a;
    }
    return re;
}
ll getf(ll k,int m)
{
    mod=m;
    matrix r=ksm(mf,k);
    return r.a[1][0];
}
int main()
{
    int ca;
    scanf("%d",&ca);
    mf.a[0][0]=mf.a[1][0]=mf.a[0][1]=1; 
    while(ca--)
    {
        ll n,a,b,c,d;
        scanf("%lld%lld%lld%lld%lld",&n,&a,&b,&c,&d);
        while(c)
        {
            b-=(a/c)*d;a%=c;
            if(aif(!a){printf("%lld\n",getf(n+1,MOD)*gcd(b,d)%MOD);continue;}
        if(!d){printf("%lld\n",(getf(n,MOD)*a%MOD+getf(n+1,MOD)*b%MOD+MOD+MOD)%MOD);continue;}
        ll g=gcd(getf(n+1,a),a),ans=gcd(a*getf(n,g*d)+b*getf(n+1,g*d),g*d);

        printf("%lld\n",abs(ans)%MOD);
    }
    return 0;
}

你可能感兴趣的:(数论)