这道很容易就得出一个公式 ax + by = N+1
我们用拓展欧几里得求得他的x极大正值解 和 极小正值解 然后 用 a*(xmax-xmin)/lcm(a,b)+1便是最终答案了
比较需要注意的是边境的处理
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
ll ex_gcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
else
{
ll r = ex_gcd(b,a%b,x,y);
ll tmp=x;
x = y;
y = tmp-a/b*y;
return r;
}
}
int main()
{
// freopen("1352.in","r",stdin);
// freopen("1352.out","w",stdout);
int t;
scanf("%d",&t);
while(t--)
{
ll n,a,b;
scanf("%lld%lld%lld",&n,&a,&b);
n++;
ll x,y;
ll r = ex_gcd(a,b,x,y);
if(n%r) printf("0\n");
else
{
ll lcm = a*b/r;
ll times = n/r;
x*=times;
y*=times;
ll aaddition = b/r;
ll baddition = a/r;
ll xmin=(x%aaddition+aaddition)%aaddition;
ll ymax=(n-a*xmin)/b;
ll ymin=(y%baddition+baddition)%baddition;
ll xmax=(n-ymin*b)/a;
// cout << "xmin " << xmin << " ymax " << ymax << endl;
// cout << "xmax " << xmax << " ymin " << ymin << endl;
if(xmin<=0)
{
xmin+=lcm/a;
ymax-=lcm/b;
if(ymax<=0)
{
printf("0\n");
continue;
}
}
if(ymin<=0)
{
ymin+=lcm/b;
xmax-=lcm/a;
if(xmax<=0)
{
printf("0\n");
continue;
}
}
printf("%lld\n",a*(xmax-xmin)/lcm+1);
}
}
fclose(stdin);
fclose(stdout);
}