poj-2115 C Looooops (单变元模线性方程)

60 篇文章 0 订阅

题意:利用了 k位存储系统 的数据特性进行循环。例如int型是16位的,那么int能保存2^16个数据,即最大数为65535(本题默认为无符号),当循环使得i超过65535时,则i会返回0重新开始计数,如i=65534,当i+=3时,i=1,其实就是 i=(65534+3)%(2^16)=1。有了这些思想,设对于某组数据要循环x次结束,那么本题就很容易得到方程: x=[(B-A+2^k)%2^k] /C,即 Cx=(B-A)(mod 2^k) 此方程为 模线性方程,本题就是求X的值。

#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <algorithm>
#define N 1010
#define LL long long
using namespace std;
/*
* 已知 a, b, n, 求x  使得ax≡b(mod n)
* 
* 令d=gcd(a, n) 先使用扩展欧几里得来求ax+ny=d的解,
* 如果b不能整除d,则无解;否则mod n意义下的解有d个,
* 可以通过对某个解不断的加n/d得到
*  
* 时间复杂度 O(log n)
* 
*/
long long extend_gcd(long long a, long long b, long long &x, long long &y){
    if (b){
        long long r = extend_gcd(b, a%b, y, x);
        y -= x*(a/b);
        return r;
    } else {
        x = 1;
        y = 0;
        return a;
    }
}

vector <long long> line_mod_equation(long long a, long long b, long long n){
    long long x, y;
    long long d = extend_gcd(a, n, x, y);
    vector<long long> ans;
    ans.clear();
    if (b%d == 0) {
        x %= n;
        x += n;
        x %= n;
        ans.push_back(x*(b/d)%(n/d));
        for (long long i = 1; i < d; i++){
            ans.push_back((ans[0]+i*n/d)%n);
        }
    }
    return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    long long a, b, c, k, aa, bb, nn, x, y, d;
    while(1){
        cin >> a >> b >> c >> k;
        if (k == 0){
            break;
        }
        aa = c;
        bb = b-a;
        nn = 1ll<<k;
        d = extend_gcd(aa, nn, x, y);
        if (bb%d == 0){
            x = (x*(bb/d))%nn;
            x = ((x%(nn/d)+nn/d))%(nn/d);
            printf("%I64d\n",x);
//            cout << x << endl //换成cout输出就会WA    为什么啊?? 
        }else{
            puts("FOREVER");
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值