给出N个固定集合{1,N},{2,N-1},{3,N-2},...,{N-1,2},{N,1}.求出有多少个集合满足:第一个元素是A的倍数且第二个元素是B的倍数。
提示:
对于第二组测试数据,集合分别是:{1,10},{2,9},{3,8},{4,7},{5,6},{6,5},{7,4},{8,3},{9,2},{10,1}.满足条件的是第2个和第8个。
Input
第1行:1个整数T(1<=T<=50000),表示有多少组测试数据。 第2 - T+1行:每行三个整数N,A,B(1<=N,A,B<=2147483647)
Output
对于每组测试数据输出一个数表示满足条件的集合的数量,占一行。
Input示例
2 5 2 4 10 2 3
Output示例
1 2
题目考点很容易看出,就是求解ax+by=n+1中解的个数
这里不能完全明白的地方是为什么除以LCM便是剩下可能的情况(巨巨们说是中国剩余定理)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<limits.h>
#include<string>
#include<queue>
#include<vector>
#include<stack>
#include<math.h>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn 1000005
#define Mod 1000000007
const int inf=1e10;
ll gcd(ll x,ll y)
{
if(y==0)return x;
return gcd(y,x%y);
}
void ex_gcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return;
}
ll x1,y1;
ex_gcd(b,a%b,x1,y1);
x=y1;
y=x1-a/b*y1;
}
int main()
{
ll n,a,b,i,j,T;
scanf("%lld",&T);
while(T--)
{
ll x,y;
scanf("%lld%lld%lld",&n,&a,&b);
n++;
ll temp=gcd(a,b),LCM=a/temp*b;
if(n%temp)
{
printf("0\n");
continue;
}
ll dn=n/temp;
ll da=a/temp;
ll db=b/temp;
ex_gcd(da,db,x,y);
x*=dn;
x=(x%db+db)%db;//求最小的非负x的解
if(x==0)
x+=db;//保证x是整数
ll ans=n-1-x*a;
//printf("%lld",a);
if(ans<0)printf("0\n");
else printf("%lld\n",1+ans/LCM);
}
}