1. 程式人生 > >qdu 2017級納新題(擴充套件歐幾里得)

qdu 2017級納新題(擴充套件歐幾里得)

在你面前撒個嬌 哎呦喵喵喵喵喵

Description

 

我們一起學貓叫

一起喵喵喵喵喵

在你面前撒個嬌

哎呦喵喵喵喵喵

我的心臟砰砰跳

迷戀上你的壞笑

你不說愛我我就喵喵喵

每當xjy和hqy一起唱起這首歌時,就會吸引好多貓群來聽歌,這天他們又吸引來n群貓。

每個貓群裡都分為雄貓和雌貓,第一個貓群裡有1只雄貓和n只雌貓,第二個貓群裡有2只雄貓和n-1只雌貓....第n個貓群裡有n只雄貓和1只雌貓。

xjy和hqy都很喜歡貓,他們對貓分別有好感度a和b,當一個貓群的雄貓數是a的倍數時,這個貓群會對xjy產生好感,同樣的,當一個貓群的雌貓數

是b的倍數時,這個貓群會對hqy產生好感。

演唱結束後,他們想帶一些貓群回他們自己的小窩,但是隻有同時對xjy和hqy都產生好感的貓群才能被帶走。

他們想知道能帶走多少貓群,但xjy在hqy面前通常比較笨,所有隻能求救於你了。

Input

 

第一行一個整數T,(1<=T<=50000),表示有T組測試樣例。

之後T行,每行三個整數分別表示n,a,b(1<=n,a,b<=2147483647)

Output

 

共輸出T行,每行對應一個測試資料,表示能帶走的貓群數量。

Sample Input 1 

2
5 2 4
10 2 3

Sample Output 1

1
2

Hint

對於第二個測試樣例,可以帶走的是2只雄貓9只雌貓的貓群和8只雄貓3只雌貓的貓群。

題意:表示選拔的時候死活一直錯很迷,後來看了學長的程式碼,換了一種寫法就對了,好迷呀,中文題,不解釋啦~~

題解:這個題就是求方程 ax+by=n+1 的正整數解的個數,先跑一遍擴充套件歐幾里得求方程 ax+by=gcd(a,b)的解,然後根據通解公式 x=x0*(n+1)/gcd+b*t/gcd  ,   y=y0*(n+1)/gcd-a*t/gcd(t 為整數) 可以計算出 x,y 的最小正整數解  x=(x0%(b/gcd)+(b/gcd) )%(b/gcd)  ( x0 可能為負數,所以要加一個(b/gcd) )   y=(y0%(a/gcd)+(a/gcd) )%(a/gcd)  ( y0 可能為負數,所以要加一個(a/gcd)) 

不要問我為什麼,記住就好了!然後就是,x的最小值對應y的最大值,根據 by=(n+1)-(a*x)求出y的最大值,然後根據通解公式可以知道y最大-y最小=y0*(n+1)/gcd-(y0*(n+1)/gcd-a*t最大/gcd=a*t最大/gcd 求出t最大,然後結果加一就好了。詳細請看程式碼:

 

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
ll n,a,b,x,y;
ll ex_gcd(ll a, ll b, ll &x, ll &y){//擴充套件歐幾里得模板
	if(b==0){
		x=1,y=0;
		return a;
	}
	ll p=ex_gcd(b,a%b,y,x);
	y-=a/b*x;
	return p;
}
int main(){
	int t;
	cin >> t;
	while(t--){
		cin >> n >> a >> b;
		ll gcd=ex_gcd(a,b,x,y);
		ll ans=0;
		if((n+1)%gcd==0){
			ll k=(n+1)/gcd;
			x*=k;//別忘記乘以(n+1)/gcd,因為所求x為ax+by=gcd(a,b)的解
			y*=k;//別忘記乘以(n+1)/gcd,因為所求y為ax+by=gcd(a,b)的解
			ll r1=b/gcd;		
			x=(x%r1+r1)%r1;
			if(x==0) x=r1;//求出非0的x的最小解的	
			ll re=n+1-x*a;
			if(re<=0) ans=0;
			else{
				ll yy=re/b;//y的最大解
				ll r2=a/gcd;
				y=(y%r2+r2)%r2;//求出非0的y的最小解
			    if(y==0) y=r2;
				ans=(yy-y)/r2+1;//最大減最小除以a/gcd+1別忘記加一
			}		
		}
		cout << ans << endl;
	}
	return 0;
}