1. 程式人生 > >解的個數(直線上的點)(數論-擴充套件歐幾里得演算法)

解的個數(直線上的點)(數論-擴充套件歐幾里得演算法)

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,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輾轉相除法/演算法求最大公約數gcdm,n

歐幾里得演算法求最大公約數:輾轉相除法 具體做法:用較小數除較大數,再用出現的餘數(第一餘數)去除除數,再用出現的餘數(第二餘數)去除除數,如此反覆,直到最後餘數是0為止。如果是求兩個數的最大公約數,

數論整數二元一次不定方程擴充套件求解

問題:形如a*x+b*y=c(a,b均不為0)的方程,a,b,c都是整數,求(x,y)整數解。 判斷是否有解 整數二元一次方程有解的充要條件是gcd(a,b)|c。如果不能整除則無解。 擴充套件歐幾里得演算法 歐幾里得演算法就是求出a*x+b*y=g