A/B HDU-1576 (乘法逆元and拓展欧几里得)

A/B HDU-1576

要求(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

题解:

需要知道(背过)的定理:逆元  (a/b) (mod N) = (a * x) (mod N)。 x表示b的逆元。并且 b*x ≡ 1 (mod N )。

题目让求A/B%9973 即A/B%9973=A*x%9973 x为B的逆元。故B*x≡1 (mod 9973)变形为B*x-9973*y=1 套用拓展欧几里得求x。又因为n=A%9973,即可以求出答案。(拓展欧几里得既可以求出a,b的最大公约数,又可以求出满足ax+by=gcd(a,b)的一组x,y的解)

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int gcd(int a,int b,int &x,int &y)
 7 {
 8     if(b==0)
 9     {
10         x=1;
11         y=0;
12         return a;
13     }
14     int q=gcd(b,a%b,y,x);
15     y-=a/b*x;
16     return q;
17 }
18 int main()
19 {
20     int n,b,x,y,t;
21     scanf("%d",&t);
22     while(t--)
23     {
24         scanf("%d%d",&n,&b);
25         gcd(b,9973,x,y);
26         x=x*n;
27         printf("%d\n",(x%9973+9973)%9973);
28     } 
29 return 0;
30 }

 

用乘法逆元的解法:

根据费马小定理,对于素数n,任意不是n的倍数的b,都有:   b^(N-1)=1(mod N)---->b*b^(N-2)=1(mod N)----->b的逆元为b^(N-2),

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 typedef long long ll;
 5 const int maxn=1e5+10;
 6 #define mod 9973
 7 using namespace std;
 8 ll powmod(ll a,ll b)
 9 {
10     ll ans=1;
11     while(b)
12     {
13         if(b&1)
14             ans=(ans*a)%mod;
15         a=(a*a)%mod;
16         b>>=1;
17     }
18     return ans%mod;
19 }
20 int t;
21 int n,b;
22 int main()
23 {
24     cin>>t;
25     while(t--)
26     {
27      scanf("%d%d",&n,&b);
28      b=b%mod;
29      printf("%lld\n",(n*powmod(b,mod-2)+mod)%mod);
30     }
31 return 0;
32 }

 

posted @ 2018-08-16 20:47  *starry*  阅读(436)  评论(0编辑  收藏  举报