同余定理:
数论中的重要概念。给定一个正整数m,如果两个整数a和b满足a-b能够被m整除,即(a-b)/m得到一个整数,那么就称整数a与b对模m同余,记作a≡b ( modm)
a
≡
b
(
m
o
d
m
)
。对模m同余是整数的一个等价关系
(a+b ) % c=(a % c+b % c) % c ( a + b ) % c = ( a % c + b % c ) % c
(a ∗ b) % c=(a % c ∗ b % c) % c ( a ∗ b ) % c = ( a % c ∗ b % c ) % c
令
a=k1∗m+r1b=k2∗m+r2 a = k 1 ∗ m + r 1 b = k 2 ∗ m + r 2
(a+b) % m=((k1∗m+r1)+(k2∗m+r2)) % m=((k1+k2)∗m+(r1+r2)) % m=(r1+r2) % m=(a % m+b % m) % m(811)(812)(813)(814) (811) ( a + b ) % m = ( ( k 1 ∗ m + r 1 ) + ( k 2 ∗ m + r 2 ) ) % m (812) = ( ( k 1 + k 2 ) ∗ m + ( r 1 + r 2 ) ) % m (813) = ( r 1 + r 2 ) % m (814) = ( a % m + b % m ) % m
所以
(a+b) % m=(a % m+b % m) ( a + b ) % m = ( a % m + b % m )
要求(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
令m=9973 m = 9973 那么
AB %;m=AB∗1 %m=AB∗B∗C%m(815)(816) (815) A B % ; m = A B ∗ 1 % m (816) = A B ∗ B ∗ C % m
即
B∗C%m=1 B ∗ C % m = 1
B∗C≡1modm B ∗ C ≡ 1 m o d m
所以
C就是B的逆元 C 就 是 B 的 逆 元
已知
B
B
,可以根据拓展欧几里德算法求得
C
C
,所以最终的结果就是
A∗Cmod9973 A ∗ C m o d 9973
由费马小定理可以得出
C=B m−2(m=9973) C = B m − 2 ( m = 9973 )
所以
ans=n∗B m−2%mans=(n%m)∗(B m−2%m)%m(为了防止数据溢出) a n s = n ∗ B m − 2 % m a n s = ( n % m ) ∗ ( B m − 2 % m ) % m ( 为 了 防 止 数 据 溢 出 )
代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef long long ll;
const int c=9973;
ll pow_mod(ll a,ll b,ll c)
{
ll ans=1;
a%=c;
while(b)
{
if(b&1) ans=ans*a%c;
a=a*a%c;
b>>=1;
}
return ans;
}
ll x,y;
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,y,x);
y-=a/b*x;
return r;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,b;
scanf("%d %d",&n,&b);
printf("%lld\n",(long long) n*(pow_mod(b,c-2,c)%c)%c);//pow_mod(b,c-2,c)就是B的逆元C
}
return 0;
}