[牛客]Rikka with Ants-类欧几里得算法--复习自用

题目

 

 分析题意

  有两只蚂蚁在一个二维平面上走,起点为(1,0)。

  Rikka 布置了三条规定:

  1. 第一只蚂蚁不能走过直线y=\frac{a}{b}x(a,b>0)

  2. 第二只蚂蚁不能走过直线y=\frac{c}{d}x(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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值