题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1576
题目大意:见题目
解题思路:开始的时候,看到求(A/B)%9973感觉像是直接利用同余公式即可解决,回顾一下同余公式:
(a+b)mod n = ((a mod n)+(b mod n))mod n
(a-b)mod n = ((a mod n)-(b mod n) + n) mod n
ab mod n = (a mod n)(b mod n) mod n于是我就想,是不是可以利用其中的乘法公式进行计算呢,过程如下:
(A/B)%9973
=(A*(1/B))%9973 也就是把A/B看成是A和1/B的乘积
=((A%9973)*(1/B%9973))%9973
=(n*(1/B%9973))%9973 因为题目中给出n=A%9973
=(n/B)%9973 题目中限制1 <= B <= 10^9,因此1/B一定<9973,即1/B%9973==1/B然后我就利用推出的这个公式进行计算,发现结果都是错的…………………………其实不难理解,公式化简到最后其实又变成了某两个数做除法再求模,但同余公式中明显没有针对除法的公式,因此这道题又一次告诉我们:没有针对除法的同余公式……………………切记切记
然后发现题目中给出了一个条件:gcd(B,9973) = 1,于是想到可以构造一个关于B和9973的等式,这样就可以利用扩展欧几里得算法解决了,推导如下:
设(A/B)%9973=k,所以A/B = 9973x+k
A = 9973Bx+kB
又因为A%9973=n
所以 (9973Bx+kB)%9973=n
所以kB%9973=n
kB = 9973y+n
kB-9973y=n
等式两边同时除以n可得:
B*k/n - 9973y/n = gcd(B,9973)=1
然后利用扩展欧几里得算法即可得到k/n的值,将其乘n可得k,为使结果>0则(k%9973+9973)%9973AC代码:
#include <iostream>
using namespace std;
#define MOD 9973
void extend_gcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return ;
}
else
{
extend_gcd(b,a%b,y,x);
y-=x*(a/b);
}
}
int main()
{
int x,y;
int t;
int n,b;
cin>>t;
while(t--)
{
cin>>n>>b;
extend_gcd(b,MOD,x,y);
x = (x%MOD+MOD)%MOD;
cout<<(x*n)%MOD<<endl;
}
return 0;
}
本文通过解析HDU 1576题目,探讨了同余公式的应用边界及扩展欧几里得算法在解决特定模运算问题中的有效性。介绍了如何利用扩展欧几里得算法求解形如(A/B)%9973的问题,并提供了AC代码。
&spm=1001.2101.3001.5002&articleId=51942539&d=1&t=3&u=ec88e28878e4474d9662298f9411ec8b)
265

被折叠的 条评论
为什么被折叠?



