qdu 2017級納新題(擴充套件歐幾里得)
在你面前撒個嬌 哎呦喵喵喵喵喵
Description
我們一起學貓叫
一起喵喵喵喵喵
在你面前撒個嬌
哎呦喵喵喵喵喵
我的心臟砰砰跳
迷戀上你的壞笑
你不說愛我我就喵喵喵
每當xjy和hqy一起唱起這首歌時,就會吸引好多貓群來聽歌,這天他們又吸引來n群貓。
每個貓群裡都分為雄貓和雌貓,第一個貓群裡有1只雄貓和n只雌貓,第二個貓群裡有2只雄貓和n-1只雌貓....第n個貓群裡有n只雄貓和1只雌貓。
xjy和hqy都很喜歡貓,他們對貓分別有好感度a和b,當一個貓群的雄貓數是a的倍數時,這個貓群會對xjy產生好感,同樣的,當一個貓群的雌貓數
演唱結束後,他們想帶一些貓群回他們自己的小窩,但是隻有同時對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))
#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;
}