题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1352
题目大意:
给出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个。
解题思路:
因为第一个元素+第二个元素等于N+1,所以可以列二元一次方程A*x+B*y=N+1求出其中一对解(x0,y0),并得到ra=A/gcd(A,B),rb=B/gcd(A,B),
接下来我们需要求出最小的x,根据方程,我们知道每当y-1则x-A/B(约分后为rb/ra),因为解是整数所以x每次只能减少rb,所以最小的x为x%rb。
于是得到(x1,y1)为x最小,y最大是的情况。接下来求总共有几组解,同理根据上面求最小的x的方法,y每次只能减少ra,x每次只能增加rb。
同时要满足两个条件:①A*x<=n ②y>0所以最后答案就为1+min(y/ra,(N-A*x)/(A*rb))。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long LL; 7 //ax+by=gcd(a,b),d为最后求出的gcd(a,b) 8 void ex_gcd(LL a,LL b,LL &x,LL &y,LL &d){ 9 if(!b){ 10 d=a; 11 x=1; 12 y=0; 13 return; 14 } 15 ex_gcd(b,a%b,y,x,d); 16 y=y-a/b*x; 17 } 18 19 LL cal(LL a,LL b,LL n){ 20 LL x,y,d; 21 n++; //n+1 22 ex_gcd(a,b,x,y,d); 23 if(n%d) //ax+by=c,gcd(a,b)|c不成立,则无解 24 return 0; 25 x*=n/d; 26 y*=n/d; 27 LL rb=b/d,ra=a/d; 28 x=(x%rb+rb)%rb; //求出最小的x,每当y-1则x-a/b(约分后为rb/ra),因为解是整数所以x每次只能减少rb,所以最小的x为x%rb。 29 y=(n-a*x)/b; //最大的y 30 if(x==0) //x不能为0 31 x+=rb; 32 if(a*x>n-1) //无解 33 return 0; 34 return 1+min(y/ra,(n-1-a*x)/(a*rb));//跟求最小的x时同理,但要满足:①a*x<=n-1 ②y>0 35 } 36 37 int main(){ 38 int t; 39 ios::sync_with_stdio(false); 40 cin>>t; 41 while(t--){ 42 int n,a,b; 43 cin>>n>>a>>b; 44 cout<<cal(a,b,n)<<endl; 45 } 46 return 0; 47 }