求gcd(afn+bfn+1,cfn+dfn+1)gcd(afn+bfn+1,cfn+dfn+1)。
首先有几个简单的性质:
gcd(fx,fy)=fgcd(x,y)gcd(fx,fy)=fgcd(x,y)
gcd(a,b)=gcd(a−kb,b)gcd(a,b)=gcd(a−kb,b)
若gcd(b,c)=1gcd(b,c)=1,那么gcd(ab,c)=gcd(a,c)gcd(ab,c)=gcd(a,c)。
先通过辗转相除把cc消成,那么只要考虑gcd(a′fn+b′fn+1,d′fn+1)gcd(a′fn+b′fn+1,d′fn+1)
首先通过矩阵乘法我们可以求出fnfn在模一个常数aa下的值,那么就可以求。
设g=gcd(fn+1,a′)g=gcd(fn+1,a′),那么答案就等于g⋅gcd(a′fn+b′fn+1g,d′fn+1g)g⋅gcd(a′fn+b′fn+1g,d′fn+1g)。
因为gcd(a′fn+b′fn+1g,fn+1g)=1gcd(a′fn+b′fn+1g,fn+1g)=1,那么答案就是g⋅gcd(a′fn+b′fn+1g,d′)=gcd(a′fn+b′fn+1,g⋅d′)g⋅gcd(a′fn+b′fn+1g,d′)=gcd(a′fn+b′fn+1,g⋅d′)。
只需要求出gcd(fn,g⋅d)gcd(fn,g⋅d)和gcd(fn+1,g⋅d)gcd(fn+1,g⋅d)即可。
注意特判a′=0a′=0和d′=0d′=0的情况。复杂度O(T⋅23logn)O(T⋅23logn)。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#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;i<h;i++)
for(int j=0;j<b.w;j++)
for(int k=0;k<w;k++)
up(re.a[i][j],a[i][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;i<a.h;i++)
re.a[i][i]=1;
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(a<c) swap(a,c),swap(b,d);
}
if(!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;
}