Jzoj 5736

1 篇文章 0 订阅
1 篇文章 0 订阅

总而言之,就是求 gcd(a*F[n]+b*F[n+1],c*F[n]+d*F[n+1])  F[n]即斐波那契数列。

开始,我们先要知道gcd和fibonacci数列之间不可描述的关系:

1.gcd(F[n],F[m])=F[gcd(n,m)]

2.gcd(a,b)=gcd(a-kb,b)

3. if(gcd(b,c)==1) gcd(a*b,c)=1;

4.gcd(a,b)=gcd(b,a mod b)

接着,我们看看原题给的式子,有a,b,c,d四个参数,考虑最基本的消参思路,将其转化为:

gcd(A*F[n]+B*F[n+1],D*F[n+1])  ①

由性质2与性质4,我们可以发现,我们利用辗转相除法,变为

gcd(c*F[n]+d*F[n+1],(a*F[n]+b*F[n+1])mod(c*F[n]+d*F[n+1]))

这样逐步消下去,就会变成①式的形式。

接着考虑对①式的转化:

g=gcd(F[n+1],A),那么答案即为g*gcd(\frac{F[n]*A+F[n+1]*B}{g},\frac{F[n+1]*D}{g})

因为gcd(F[n]*A,F[n+1])<=gcd(A,F[n+1]),

所以gcd(\frac{F[n]*a+F[n+1]*B}{g},\frac{F[n+1]}{g})==1

所以由性质3,答案即为gcd(F[n]*A+F[n+1]*B,D*g);

同时我们还可以用矩阵乘法求gcd(F[n],a)=gcd(F[n]moda,a)

#include<bits/stdc++.h>
using namespace std;
#define in inline
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repd(i,a,b) for(int i=a;i>=b;i--)
#define For(i,a,b) for(int i=a;i<b;i++)
#define _(d) while(d(isdigit(ch=getchar())))
template<class T>in void g(T&t){T x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;t=f*x;}
typedef long long ll;
const ll MOD=998244353;
ll mod;
struct matrix{
	ll a[5][5];
	in void init(){a[1][1]=1,a[1][2]=0,a[2][1]=0,a[2][2]=1;}
	in void Clear(){memset(a,0,sizeof(a));}
	in void unit(){a[1][1]=1,a[1][2]=1,a[2][1]=1,a[2][2]=0;} 
	in matrix operator*(const matrix tt)const{
		matrix c;c.Clear();
		rep(i,1,2) rep(j,1,2) rep(k,1,2) 
			c.a[i][j]=(c.a[i][j]+a[i][k]*tt.a[k][j]+mod)%mod; 
		return c;
	}
	in matrix operator^(ll y){
		matrix tmp,c=*this;tmp.init();
		while(y){
			if(y&1) tmp=tmp*c;
			c=c*c;y>>=1;
		}return tmp;
	} 
}e;
ll n,a,b,c,d;
in ll F(ll x,ll M){
	mod=M;
	matrix tmp=e^(x);
	return tmp.a[1][2]%mod;
}
int main(){
	//freopen(".in","r",stdin);freopen(".out","w",stdout);
	int T;g(T);e.unit();
	while(T--){
		g(n),g(a),g(b),g(c),g(d);
		while(c){
			b-=(a/c)*d;a%=c;
			if(a<c) swap(a,c),swap(b,d); 
		}
		if(!a){
			ll ans=F(n+1,MOD)*__gcd(b,d);
			printf("%lld\n",(ans%MOD+MOD)%MOD);
		}
		else if(!d){
			ll ans=F(n,MOD)*a%MOD+F(n+1,MOD)*b%MOD;
			printf("%lld\n",(ans%MOD+MOD)%MOD);
		}
		else{
			ll h=__gcd(F(n+1,a),a);
			ll ans=__gcd(a*F(n,h*d)+b*F(n+1,h*d),h*d);
			printf("%lld\n",abs(ans)%MOD);
		}
	}
	return 0;
}

若有错误请指正谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可爱の小公举

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值