题目
分析题意
有两只蚂蚁在一个二维平面上走,起点为(1,0)。
Rikka 布置了三条规定:
1. 第一只蚂蚁不能走过直线(a,b>0)
2. 第二只蚂蚁不能走过直线(c,d>0)
3. 所有蚂蚁都不能走过直线 y=0
每一只蚂蚁的行走方式都是一样的:如果能往上走,那么向上;否则向右。
问这两只蚂蚁走过的路径上有多少个整点是重合的,如果答案为无穷多个,输出 -1
分析见图片:
类欧几里得算法
先附上最基础的f(a,b,c,n)代码:
ll f_gcd(ll a,ll b,ll c,ll n)
{
ll m=(a*n+b)/c;
if(n==0||m==0) return b/c;
if(a>=c||b>=c) return (n*(n+1)/2)*(a/c)+(n+1)*(b/c)+f_gcd(a%c,b%c,c,n);
else return n*m-f_gcd(c,c-b-1,a,m-1);
}
递归求解即可,注意在计算m 时,an用long long 可能会爆,用__int128
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int128 lll;
#define mod 998244353
ll f_gcd(ll a,ll b,ll c,ll n)
{
if (a==0)
return (b/c)%mod*((n+1)%mod)%mod;
if (a>=c||b>=c)
return ((ll)((lll)a/c%mod*(n*(n+1)/2%mod))%mod+(b/c)*(n+1)%mod+f_gcd(a%c,b%c,c,n))%mod;
ll tmp=((lll)a*n+b)/c;
return (tmp%mod*n%mod-f_gcd(c,c-b-1,a,tmp-1)+mod)%mod;
}
int main()
{
int T;
cin>>T;
while(T--)
{
ll a,b,c,d;
scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
if(a*d==b*c)
{
printf("-1\n");
continue;
}
if(c*b>a*d)
{
swap(a,c);
swap(b,d);
}
ll Xmax=d*(a+b)/(a*d-b*c);
ll S1=f_gcd(c,c,d,Xmax-1);
ll S2=f_gcd(a,0,b,Xmax-1);
ll ans=((S1+mod-S2)%mod+Xmax%mod+mod)%mod;
printf("%lld\n",ans);
}
return 0;
}