P1082 [NOIP2012 提高组] 同余方程
问题转化
题目问的是满足
但是不能暴力枚举
把问题转化一下。观察
问题还需要转化。扩展欧几里得是用来求
原理是,方程
这个简单证一下。
由最大公因数的定义,可知
因为
那么
可得出在这道题中,方程
扩展欧几里得
前提:知道普通欧几里得算法(辗转相除法)。
下面字母挺多,希望你耐心地慢慢地读~
我们拿到了一组
(注意,虽然刚刚已经证明本题的
如果我们先前已经求出了另一组数
可见,在这个“如果”实现的时候,我们的目标变成了“求出满足上式的
其中
怎么求呢?取模运算是
看上面这个方程,一组必然存在的解出现了:
可见,我们只要求出
现在我们手上是
把①和②对比一下:
原方程中的系数
所以,把新的方程也看作
再一模一样下来,我们又需要
……
这个递归中
这时要直接返回了,我们需要一组
然而该层的
(最后一层的 long long
,通过了此题。)
最后一层结束后,就开始返回,直到最上层。每一层可以轻松地根据下层的
整个过程就是:以辗转相除的方式向下递进,不断缩小系数,保证会出现有确定解的最后一层。
答案处理
一个遗留问题:我们将要求出来的
1.显然这并不会把方程中任何整数变成非整数。
2.“加上或减去
已经求出一组整数
现在想改变
仅当
因此到最后,如果
x = (x % b + b) % b;//括号中取模再加,可以处理负数
代码
推导中的所有 long long x, y
,传递也很方便。
#include<bits/stdc++.h>
using namespace std;
long long x, y;//目前方程真正的解
void exgcd(long long a, long long b)
{
//当前目的:求解 ax + by = gcd(a, b) 这么一个方程
if(b == 0) //a, b不断改变的过程中,b最终必然会成为0
{
//在 b = 0 时方程还要成立? 使 x = 1, y = 0 ,必然成立
x = 1;
y = 7; //建议返回0。不过y = 7能AC,证明了最后一个等式不受最后一个y影响
return;
}
exgcd(b, a % b);//把下一层系数传进去(先求下一个方程的解 )
//现在我们已经拿到了下一个方程的解x, y
long long tx = x;//暂时存一下x,别丢了
x = y;
y = tx - a / b * y;
}
int main()
{
long long a, b;
cin >> a >> b;
exgcd(a, b);
x = (x % b + b) % b;//我们求出来的x必然满足方程,但不一定是最小正整数解,所以要进行答案处理
printf("%lld\n", x);
return 0;
}
求这样一个满足
这个
在模
假设我们已经算出了:
ans = (a * b * c) % p;
现在要从
如果像下面这样直接除会出错(举个实例会很直观):
ans = ans / b % p;
所以我们就求出
ans = ans * x % p;
原理可以这么理解:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】