C Looooops POJ - 2115 (深入理解扩欧算法)

这篇博客探讨了一道程序设计题目,涉及将数学问题转化为求最小非负数解的问题。通过使用扩展欧几里得算法(exgcd),博主解析了如何找到整数方程的解,并提供了详细的代码实现。文章强调了特殊情况的处理,如当B等于A时答案为0,以及c小于0时的解法。整个过程展示了将算法应用于解决实际编程挑战的方法。
摘要由CSDN通过智能技术生成

传送门

题意:多组输入,每组给A,B,C,k(0<=A,B,C<2^k)。求出statement运行了多少次?

注意variable对2^k取余。

题解:转化为已有知识,(A+C*x)\equiv B(mod\2^k)=>c*x-2^k*y=B-A,解最小的非负数x。

注意事项:

  • 注意B=A的时候答案直接为0
  • 如果a==0,b==0,exgcd那应该是没有解的,返回-1。好在这里不可能b=2^k=0。
  • 这里c,2^k都为非负数,c=B-A如果小于0,那就先f=-1,然后解a*x+b*y=-c的最小的非负数解,然后后mod_x-x即为a*x+b*y=c的最小非负数解(这里要对exgcd算法有深入的理解
  • 其他都是比较常规的操作了

代码:

#include <cstdio>
#include <iostream>

#define int long long
#define read(x) scanf("%lld", &x)
#define print(a, c) printf("%lld%c", a, c)
#define dbg(x) cout << #x << "===" << x << endl;
#define pb push_back
using namespace std;
const int N = 1e5 + 10;

int A, B, C, k;
int qpow(int a, int p) {
    int res = 1;
    while (p) {
        if (p & 1) res *= a;
        p >>= 1, a *= a;
    }
    return res;
}
int exgcd(int a, int b, int &x, int &y) {
    if (a == 0 && b == 0) return -1;  //不可能的情况吧
    if (!b) {
        x = 1, y = 0;
        return a;
    }
    int g = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return g;
}
signed main() {
    while (scanf("%lld%lld%lld%lld", &A, &B, &C, &k) != EOF) {
        if (A + B + C + k == 0) break;
        int a = C, b = qpow(2, k), c = B - A;  // a*x+b*(-y)=c。以下都不用考虑y
        if (c == 0) {
            puts("0");
            continue;
        }
        int f = 1;
        if (c < 0) c = -c, f = -1;  //先解a*x+b*y=-c,然后再处理a*b+b*y=c
        int X0, Y0;
        int g = exgcd(a, b, X0, Y0);
        if (c % g)
            puts("FOREVER");
        else {
            int mod_x = b / g;  //还是用a,b,c,x,y,X0,Y0,g这些我常用的符号好
            int ans = (c / g * X0 % mod_x + mod_x) %
                      mod_x;  // a*x+b*y=-c的x的最小正整数解
            if (f == -1)
                ans = mod_x - ans;  // 转化得到a*x+b*y=c的x的最小正整数解
            // cout << ">>>>>>>>>>>>>";
            print(ans, '\n');
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值