同余方程 P2613 (4/11补档正确做法)

P2613 同余模板
蒻蒟看不懂扩展欧几里得,就死记硬背了

//求关于 x 的同余方程 ax≡1(modb) 的最小正整数解
LL x,y;//目前方程真正的解 
void work(LL a,LL b)
{
	//当前目的:求解 ax + by = gcd(a, b) 这么一个方程
	if(b==0)//a, b不断改变的过程中,b最终必然会成为0
	{
		//在 b = 0 时方程还要成立? 使 x = 1, y = 0 ,必然成立
		x=1;
		y=0;
		return;
	}
	work(b,a%b);
	LL tempx=x;
	x=y;
	y=tempx-a/b*y;
}
int main() {
	LL a,b;
	cin>>a>>b;
	work(a,b);
	x=(x%b+b)%b;//我们求出来的x必然满足方程,但不一定是最小正整数解,所以要进行答案处理
	cout<<x;//如果 ax≡1(modb) 中的 1 为 μ ,则要变为 μ * x % b; 
	return 0;
}

另外,由于数据过大,需要使用快读的同时取模

inline LL read()
{
	LL res=0;
	char ch=getchar();
	while(!isdigit(ch) && ch!=EOF) ch=getchar();
	while(isdigit(ch))
	{
		res=(res<<3)+(res<<1)+(ch-'0');
		//若数很大,则取模 res%=MOD;
		ch=getchar();
	}
	return res;
}

(补档内容)

#include <bits/stdc++.h>
using namespace std;
typedef long long int LL;

LL x, y, gcd;

// 扩展欧几里得算法
void exgcd(LL a, LL b) {
    if (b == 0) {
        x = 1, y = 0;
        gcd = a;
        return;
    }
    exgcd(b, a % b);
    LL temp = x;
    x = y;
    y = temp - (a / b) * y;
}

// 计算 ax ≡ c (mod b) 的最小非负整数解
LL solve(LL a, LL b, LL c) {
    exgcd(a, b);
    
    // 如果 c 不是 gcd(a, b) 的倍数,则无解
    if (c % gcd != 0) return -1;
    
    // 计算初始解 x0 = x * (c / gcd)
    x *= c / gcd;
    b = abs(b / gcd);  // 约简 b,确保 x 归一化到 [0, b)

    // 归一化 x 到 [0, b)
    x = (x % b + b) % b;
    return x;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    LL a, b, c;
    cin >> a >> b >> c;

    LL result = solve(a, b, c);
    if (result == -1) 
        cout << "No solution" << endl;
    else 
        cout << result << endl;

    return 0;
}

posted @ 2025-02-28 00:00  石磨豆浆  阅读(14)  评论(0)    收藏  举报