HDU 1576 A/B

题目链接

A/B
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 13503 Accepted Submission(s): 10880

Problem Description
要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。

Input
数据的第一行是一个T,表示有T组数据。
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。

Output
对应每组数据输出(A/B)%9973。

Sample Input
2
1000 53
87 123456789
Sample Output
7922
6060

扩展欧几里得算法,挺基础的最最近在学,感觉入门熟悉挺适合的。
设上述要求求的公式的解为d,则推导公式可以发现 n-B*d 为9973 的倍数,即可等价为 n-Bd=9973x ,左右移项得 Bd+9973x=n , 而题目中给定gcd(B,9973) = 1,则d必定有解,用板子解出答案d即可。

上代码

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 7;
int gcd(int a, int b){
	return b == 0 ? a : gcd(b, a%b);
}
ll exgcd(ll a, ll b, ll &x, ll &y){//扩展欧几里得板子
	if (b == 0){
		x = 1; y = 0;
		return a;
	}
	ll r = exgcd(b, a%b, x, y);
	ll temp = y;
	y = x - (a / b)*y;
	x = temp;
	return r;
}
int main(){
	int T;
	ll A, B, a, b, c, x, y, z, g, m, n;
	while (scanf("%d", &T) != EOF){
		while (T--){
			scanf("%lld%lld", &n, &B);
			a = B, b = 9973, c = n;
			g = exgcd(a, b, x, y);
			x *= c / g;
			while (x < 0)x += b;
			cout << x % 9973 << endl;
		}
	}
	return 0;
}

你可能感兴趣的:(acm,算法)