HDU 1576 A/B(扩展欧几里得,思维)

题目连接:点击打开链接


解题思路:

由题知:n=A%9973,

欧几里得可化为:A=9973*k1+n代入所求式子:
((9973*k1+n)/B)%9973)=x(记为x)
即为:(9973*k1+n)%9973=B*x,可化为:
9973*k1+n=9973*k2+B*x,可化为:

B*x-n=9973 *(k1-k2)=9973*y (B*x-n与9973成倍数关系)

可化为:B*x-9973*y=n

根据扩展欧几里得可知:gcd(B,9973)=1=n,因为x是B的乘法逆元,


接着乘法逆元讲,一般,我们能够找到无数组解满足条件,但是一般是让你求解出最小的那组解,怎么做?我们求解出来了一个特殊的解 x0 那么,我们用 x0 % 9973其实就得到了最小的解了。为什么?


可以这样思考:假设 a*x + m*y = 1


x 的通解不是 x0 + m/gcd*t 吗?(t为常数,这里的gcd为1)

那么,也就是说, a 关于m的逆元是一个关于m同余的,那么根据最小整数原理,一定存在一个最小的正整数,它是 a 关于m的逆元,而最小的肯定是在(0 , m)之间的,而且只有一个,这就好解释了。

但是,由于问题的特殊性,有时候我们得到的特解 x0 是一个负数,还有的时候我们的 m 也是一个负数这怎么办?

当 m 是负数的时候(该题化简出来的式子里-9973是负数),我们取 m 的绝对值就行了,当 x0 是负数的时候,他模上 m 的结果仍然是负数。

故x,y有一组唯一的解,所以x的解唯一。



代码如下:

#include<iostream>
using namespace std;
#define ll long long

int n;
ll b;
int t;

int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>b;
        int i;
        for(i=1; i<9973; i++)
        {
            if((b*i-n)%9973==0)
                cout<<i<<endl;
        }
    }
    return 0;
}



~step by step



发布了37 篇原创文章 · 获赞 23 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/zsheng_/article/details/77044602