• POJ2115 C Looooops(数论)


    题目链接

    分析:

    数论了解的还不算太多,解的时候,碰到了不小的麻烦。

    设答案为x,n = (1<<k), 则 (A+C*x) % n == B

    即 (A+C*x) ≡ B (mod n)

    化简得 C*x ≡ (B-A) (mod n)

    设 a = C, b = (B-A)

    则原式变为 ax=b.解 x。

    到这里,以为求出来 a 的逆, 然后 x = b*a-1

    a 的 逆好求,用《训练指南》上的模板(P122) inv函数. 

    例如,求 2 模 66536 下的逆, inv(2, 66536) 便可, 但 inv(LL a, LL n) 这个函数的要求就是如果 a 和 n 的最大公约数不为1,则逆不存在。 但样例是有解的。

    在网上查了一下,说是《算法导论》(第三版)P555页有解法, 便根据书上的解法解 x 了。

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <algorithm>
    #include <cmath>
    #include <string>
    #include <map>
    #include <set>
    
    using namespace std;
    
    typedef long long LL;
    
    void gcd(LL a, LL b, LL &d, LL &x, LL &y) {
        if(!b) { d = a; x = 1; y = 0; }
        else { gcd(b, a%b, d, y, x); y-= x*(a/b); }
    }
    
    int main() {
        LL A, B, C, k, n, x, y, d;
    
        while(cin >> A >> B >> C >> k) {
            if(A == 0 && B == 0 && C == 0 && k == 0) break;
    
            n = (1LL << k);
    
            LL a = C;
            LL b = (B-A+n)%n;
    
            if(b == 0) { printf("0
    "); continue; }
    
            gcd(a, n, d, x, y);
    
            if(b % d == 0) {
                LL x0 = (x*(b/d)) % n;
                LL minn = (x0%(n/d)+n/d)%(n/d);
                cout << minn << endl;
            }
            else printf("FOREVER
    ");
        }
    
        return 0;
    }
  • 相关阅读:
    荷兰国旗问题
    读取文件中数据到数组
    从五个球中选出3个枚举的简单运用
    搜索算法总结
    匿名对象
    欧几里得距离C++代码实现
    用递归法吧字符串S倒序
    利用系统来完成十进制,十六进制,八进制的转换
    DBHelper 使用的是存储过程
    DBHelper的一个小例子
  • 原文地址:https://www.cnblogs.com/tanhehe/p/3175229.html
Copyright © 2020-2023  润新知