HDU 1576 A/B

题意很清楚,给出n = A % 9973, B gcd(B, 9973)为1, 求(A/B)%9973.

模运算有很多性质:(a+b) % c==(a % c + b % c)  %c , (a-b) % c==(a % c - b % c) % c, (a*b) % c==(a % c * b % c) % c,遗憾的是除法没有这个性质.

不过可以通过求B的乘法逆元来求得.

解法:(a / b) % c == a * b^(-1) % c 其中b^(-1)为b的乘法逆元,乘法逆元可以通过拓展欧几里得算法求得.

推导:(a / b) ≡ x (mod c) ==>两边乘上一个b得到a ≡ bx (mod c) ==>两边乘上b mod n的乘法逆元得到 ==>a * b^(-1) ≡ b * b^(-1) * x (mod c) ==> a * b^(-1) ≡ x (mod c) 

这种方法只能在gcd(b,c)为1的情况下使用,题目正好符合这个情况.

#include <cstdio>
using namespace std;

int ext_gcd(int a, int b, int & x, int & y){
	if(!b){
		x = 1, y = 0;
		return a;
	}
	int gcd = ext_gcd(b, a % b, x, y);
	int t = x;
	x = y;
	y = t - a / b * y;
	return gcd;
}

int inv(int a, int n){
	int x, y, gcd;
	gcd = ext_gcd(a, n, x, y);
	return gcd == 1 ? (x + n) % n : -1;
}
int main(int argc, char const *argv[]){
	int T;
	scanf("%d", &T);
	while(T--){
		int n, B;
		scanf("%d %d", &n, &B);
		int inverse = inv(B, 9973);
		printf("%d\n", (n * inverse) % 9973);
	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值