POJ2115 C-Loop

传送门

这道题是求解不定方程的一道好练习题。

题目描述的很诡异……还说什么k进制,其实就是要求一个数A,每次加C,问到B要加多少次,所有的数对2k取模。

也就是说我们能列出如下方程:A+xC ≡ B (mod 2k
我们把这个方程两边移项转化,那么就能得到一个不定方程的形式。

老套路,判断有没有解,否则用exgcd求解。

本题有小坑,你在1<<32的时候,即使变量开了longlong也不行,必须写成1ll的形式,否则会WA。

看一下代码。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
#include<queue>
#define pb push_back
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('
')

using namespace std;
typedef long long ll;
const int M = 40005;
const int N = 2000005;
const int INF = 1000000009;
const ll mod = 51123987;

ll read()
{
    ll ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
    if(ch == '-') op = -1;
    ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
    ans *= 10;
    ans += ch - '0';
    ch = getchar();
    }
    return ans * op;
}

ll a,b,c,k,x,y,p,q,s;

ll gcd(ll a,ll b)
{
    return (!b) ? a : gcd(b,a%b);
}

ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b)
    {
    x = 1,y = 0;
    return a;
    }
    ll d = exgcd(b,a%b,y,x);
    y -= a/b * x;
    return d;
}

int main()
{
    while(1)
    {
    a = read(),b = read(),c = read(),k = read();
    if(!a && !b && !c && !k) break;
    p = c,q = 1LL << k,s = (b-a+q) % q;
    ll G = gcd(p,q);
    if(s % G)
    {
        printf("FOREVER
");
        continue;
    }
    p /= G,q /= G,s /= G;
    exgcd(p,q,x,y);
    x = (x + q) % q,x *= s,x %= q;
    printf("%lld
",x);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/captain1/p/9781254.html