解的個數(直線上的點)(數論-擴充套件歐幾里得演算法)
已知x,y滿足如下條件:
ax+by+c=0 ; x1 <= x <= x2 ; y1 <= y <= y2 ; x,y均為整數。
其中:a,b,c,x1,x2,y1,y2 都是絕對值不超過 10^8 的整數。
求(x,y)的解的個數。
Input
第一行:n 說明:有 n 個任務。n<=10 一下有 n 行,每行為:a,b,c,x1,x2,y1,y2
Output有n行,第i行是第i個任務的結果。
分析:
裸的擴充套件歐幾里得,但有幾個坑點值得注意:
1,輸入c之後直接 c=-c
2,a==0&&b==0的情況,還需要判斷c==0
3,閉區間做減法還需要+1
4,正常情況下,求出了方程ax+by=c的一組解(注意不是ax+by=GCD(a,b)),x0和y0以及GCD(a,b)=g;設ap=a/g,bp=b/g,對於[x1~x2]來講,這個k最小應該是(x1-x0)/bp 。一般可能會想到分別求x,y的k的範圍然後求交集,但是考慮到可能除不盡,還有正負%@#*&¥#*%¥......所以就像李大神寫的一樣,列舉k就可以了,至於k需不需要加減1,順便就判斷了(不要問為什麼用long long):
--------------------------------------------------
LL bp=b/g,ap=a/g;
LL k=(x1-x0)/bp;
LL ans=0;
for(;x0+k*bp<=x2;k++)
if(y0-k*ap<=y2&&y0-k*ap>=y1&&x0+k*bp>=x1) //*
ans++;
printf("%lld\n",ans);
-----------------------------------------------------
注:上面*處, x0+k*bp>=x1 的判斷就是為了避免k需要加減1帶來的影響。
#include<cstdio> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; LL n; LL exgcd(LL a,LL b,LL &x,LL &y) { if(b==0) {x=1;y=0;return a;} LL xx,yy,g=exgcd(b,a%b,xx,yy); x=yy;y=xx-(a/b)*yy; return g; } int main() { // freopen("in.txt","r",stdin); scanf("%lld",&n); LL a,b,c,x1,x2,y1,y2; while(n--) { scanf("%lld%lld%lld%lld%lld%lld%lld",&a,&b,&c,&x1,&x2,&y1,&y2); c=-c; if(x1>x2||y1>y2) { printf("0\n"); continue; } else if(a==0&&b==0) { if(c==0) printf("%lld\n",(y2-y1+1)*(x2-x1+1)); else printf("0\n"); continue; } else if(a==0&&b!=0) { if(c%b==0&&c/b>=y1&&c/b<=y2) printf("%lld\n",x2-x1+1); else printf("0\n"); continue; } else if(a!=0&&b==0) { if(c%a==0&&c/a>=x1&&c/a<=x2) printf("%lld\n",y2-y1+1); else printf("0\n"); continue; } LL x0,y0; LL g=exgcd(a,b,x0,y0); if(c%g!=0) { printf("0\n"); continue; } x0=c*x0/g,y0=c*y0/g; LL bp=b/g,ap=a/g; LL k=(x1-x0)/bp; LL ans=0; for(;x0+k*bp<=x2;k++) if(y0-k*ap<=y2&&y0-k*ap>=y1&&x0+k*bp>=x1) ans++; printf("%lld\n",ans); } return 0; }
相關推薦
解的個數(直線上的點)(數論-擴充套件歐幾里得演算法)
Description 已知x,y滿足如下條件: ax+by+c=0 ; x1 <= x <= x2 ; y1 <= y <= y2 ; x,y均為整數。 其中:a,b,c,x1,x2,y1,y2 都是絕對值不超過 10^8 的整數。 求(x,
POJ-1061-青蛙的約會 (擴充套件歐幾里得演算法)
原題連結: http://poj.org/problem?id=1061 兩隻青蛙在網上相識了,它們聊得很開心,於是覺得很有必要見一面。它們很高興地發現它們住在同一條緯度線上,於是它們約定各自朝西跳,直到碰面為止。可是它們出發之前忘記了一件很重要的事情,既沒有問清楚對方的特徵,也沒有約定
HDU-2669-Romantic (擴充套件歐幾里得演算法)
原題連結: http://acm.hdu.edu.cn/showproblem.php?pid=2669 The Sky is Sprite. The Birds is Fly in the Sky. The Wind is Wonderful. Blew Throw the Trees
POJ-2142-The Balance (擴充套件歐幾里得演算法)
原題連結: Ms. Iyo Kiffa-Australis has a balance and only two kinds of weights to measure a dose of medicine. For example, to measure 200mg of aspiri
各種密碼學演算法的GUI程式設計實現(DES、AES、Present、擴充套件歐幾里得演算法、素性檢測)
encryption-algorithm 各種密碼學演算法的 C# GUI程式設計實現,包含: DES AES Present 擴充套件歐幾里得演算法 素性檢測 最終的結果 DES加密 DES解密
POJ 2115 for求迴圈次數-數論-(同餘方程+擴充套件歐幾里得演算法)
題意:給定for迴圈的初始值,結束值和增量,還有一個模,求最少的迴圈次數。 分析: 讀完題後應該就知道是一個同餘的概念,所以就是解一個一元一次同餘方程,像上題一樣用擴充套件歐幾里得演算法。這題的trick點是k最大為32,那麼2^32超出了int,要用long long,所
51nod 1256 乘法逆元(擴充套件歐幾里得演算法)
思路1:把k*M%N=1可以寫成一個不定方程,(k*M)%N=(N*x+1)%N,那麼就是求k*M-N*x=1使得k最小,不定方程利用擴充套件歐幾里得演算法 --------------------------------------------------------
擴充套件歐幾里得演算法(乘法逆元 最小正整數解 直線上的整數點)
參考資料: 本文證明過程來自百度百科和劉汝佳的演算法入門經典。 擴充套件歐幾里得演算法介紹: 前置知識:歐幾里得演算法(其實就是輾轉相除法,用於計算兩個整數a,b的最大公約數。) 歐幾里得演算法: 在開始之前,我們先說明幾個定理: gcd(a,b)=gcd(b,a
兩個數的生成範圍(兩個生成元)(拓展歐幾里得演算法)
最近遇到一個題,就是給兩個數,這兩個數有無限個,問你由這些數能得到哪些數。 還可以擴充套件成有n個數,問你能得到哪些數 這裡其實是有一個結論的,就是: ①兩個數互質,就可以生成很多很多數,而且從某個數開始就是連續的 ②兩個數不互質,生成的數一定是gcd(a,b)的
同餘定理(歐幾里得演算法)
如果 (a-b)%m==0 那麼 a%m==0 b%m==0 a,b關於模m同餘。 求最大公約數 #include "pch.h" #include<iostream> #include<cstdio> #include<
演算法複習——擴充套件歐幾里得演算法(擴充套件歐幾里得,逆元,整除)
①歐幾里得演算法 就是求gcd的有趣的輾轉相除法,不再贅述啦0v0 程式碼: int gcd(int a,int b) { if(b==0) return a; else return gcd(b,a%b); } ②擴充套件歐幾里得演算法 需要解決這樣的問題:兩個非0整數a,b
C語言輾轉相除/相減法(歐幾里得演算法)求最大公約數和最小公倍數
#include <stdio.h> #include <stdlib.h> //題目:輸入兩個正整數m和n,求其最大公約數和最小公倍數。 //採用任何兩種演算法來完成上述題目,並比較2種演算法的時間複雜度和空間複雜度。 int main() { int
同餘方程(擴充套件歐幾里德演算法)
同餘方程 時間限制: 1 Sec 記憶體限制: 128 MB 題目描述 求關於 x 的同餘方程 ax ≡ 1 (mod b)的最小正整數解。 輸入 輸入只有一行,包含兩個正整數 a, b,用一個空格隔開。 輸出 輸出只有一行,包含
BZOJ ~ 1385 ~ Division expression (歐幾里得演算法)
題解 原式化為情況下最有可能。然後看能否把x2的約去即可。當然不能把上面那個數字乘出來了,它太大了,所以我們拿上面的每一個數字和x2去約GCD即可。 #include<bits/stdc+
poj 1061 青蛙的約會(拓展歐幾里得演算法)
【題目】 【題意】 兩隻青蛙在給定長度的數軸上運動,給定初始位置和跳躍每次的長度,問在什麼時候兩隻青蛙能相遇。 【思路】 根據題意有x+mt=y+nt+kl,t表示跳躍次數。變化一下得到式子
Wannafly summer camp Day2 ——Utawarerumono(數論擴充套件歐幾里得)
9511: Utawarerumono 時間限制: 1 Sec 記憶體限制: 128 MB 提交: 389 解決: 66 [提交] [狀態] [討論版] [命題人:admin] 題目描述 算術是為數不多的會讓久遠感到棘手的事情。通常她會找哈克幫忙,但是哈克已經被
擴充套件歐幾里得演算法(求乘法逆元)
eg:求5關於模14的乘法逆元 15 = 5*2+1 5 = 4*1+1 說明5與14互素,存在5關於14的乘法逆元 1 = 5-4 = 5-(14-5*2)= 5*3-14 因此5關於模14的乘法逆元為3 a存在模b的乘法逆元的充要條件是gcd(a,b)= 1 互質
演算法學習(一)——歐幾里德演算法&擴充套件歐幾里得演算法
最大公約數/歐幾里德演算法(gcd) 歐幾里德演算法又稱輾轉相除法,證明可以度娘。 個人簡單腦部就是a和b兩個數的模還是a和b的最大公約數 int型別 int gcd(int a, int b) {return a%b==0?b:gcd(b,a%b);} long l
Python程式碼筆記(1)輾轉相除法/歐幾里得演算法求最大公約數gcd(m,n)
歐幾里得演算法求最大公約數:輾轉相除法 具體做法:用較小數除較大數,再用出現的餘數(第一餘數)去除除數,再用出現的餘數(第二餘數)去除除數,如此反覆,直到最後餘數是0為止。如果是求兩個數的最大公約數,
(數論)整數二元一次不定方程(擴充套件歐幾里得求解)
問題:形如a*x+b*y=c(a,b均不為0)的方程,a,b,c都是整數,求(x,y)整數解。 判斷是否有解 整數二元一次方程有解的充要條件是gcd(a,b)|c。如果不能整除則無解。 擴充套件歐幾里得演算法 歐幾里得演算法就是求出a*x+b*y=g