poj2115--C Looooops(扩展gcd)

C Looooops

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 17740   Accepted: 4600

Description

A Compiler Mystery: We are given a C-language style for loop of type

for (variable = A; variable != B; variable += C)

  statement;

I.e., a loop which starts by setting variable to value A and while variable is not equal to B, repeats statement followed by increasing the variable by C. We want to know how many times does the statement get executed for particular values of A, B and C, assuming
that all arithmetics is calculated in a k-bit unsigned integer type (with values 0 <= x < 2k) modulo 2k.

Input

The input consists of several instances. Each instance is described by a single line with four integers A, B, C, k separated by a single space. The integer k (1 <= k <= 32) is the number of bits of the control variable
of the loop and A, B, C (0 <= A, B, C < 2k) are the parameters of the loop.

The input is finished by a line containing four zeros.

Output

The output consists of several lines corresponding to the instances on the input. The i-th line contains either the number of executions of the statement in the i-th instance (a single integer number) or the word FOREVER
if the loop does not terminate.

Sample Input

3 3 2 16
3 7 2 16
7 3 2 16
3 4 2 16
0 0 0 0

Sample Output

0
2
32766
FOREVER

Source

题目大意初始值是a,每一次加c ,可以对得到的值取模2^k,在值为b时结束,问最少会执行多少次,如过一直不会停FOREVER

由题中大意的到等式,假设一定会停,那么在循环x次后会等于b   也就是  (a + x*c)% (2^k)= b 。很明显的扩展gcd的题目,得到等式, a + c*x - b = y*(2^k) 也就是

求解 c*x - (2^k)*y = b-a ,问有没有整数解。

对于a*x1 + b*y1 = c ,用扩展gcd,求解 a*x1 + b*y1 = gad(a,b) = gcd(b,a%b)  = a*y2 +b* (x2-a/b*y2)得到  x1 = y2 , y1 = ( x2 +a/b*y2 ) , 利用这个等式,可以推到b = 0 时,那是x = 1 , y = 0 ,最大公约数为a,在逐层返回,最终得到 a*x1 + b*y1 = gad(a,b) 的解,如果c%( gcd(a,b) ) == 0 那么a*x1 + b*y1 = c有整数解,令d =
gcd(a,b),d = b / d.最小的正整数解围 x = ( x%d +d )%d.

#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL __int64
using namespace std;
void gcd(LL a,LL b,LL &d,LL &x,LL &y)
{
    if(b == 0)
    {
        d = a ;
        x = 1 ;
        y = 0 ;
    }
    else
    {
        gcd(b,a%b,d,y,x);
        y = -y ; x = -x ;
        y += a/b*x ;
    }
    return ;
}
int main()
{
    LL k , a , b , c , d , x , y ;
    while(scanf("%I64d %I64d %I64d %I64d", &a, &b, &c, &k)!=EOF)
    {
        if(a == 0 && b == 0 && c == 0 && k == 0)
            break;
        k = ( (LL)1 )<<k ;
        gcd(c,k,d,x,y);
        if( (b-a)%d )
            printf("FOREVER\n");
        else
        {
            x = (b-a)/d*x ;
            k = k/d ;
            x = (x%k+k)%k ;
            printf("%I64d\n", x);
        }
    }
    return 0;
}

poj2115--C Looooops(扩展gcd),布布扣,bubuko.com

时间: 2024-11-15 08:43:53

poj2115--C Looooops(扩展gcd)的相关文章

POJ2115 C Looooops 扩展欧几里德

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ2115 题意 对于C的for(i=A ; i!=B ;i +=C)循环语句,问在k位存储系统中循环几次才会结束.若在有限次内结束,则输出循环次数.否则输出死循环. 题解 原题题意再次缩略: A + xC Ξ B (mod 2k) 求x的最小正整数值. 我们把式子稍微变一下形: Cx + (2k)y = B-A 然后就变成了一个基础的二元一次方程求解,扩展欧几里德套套就可以了. 至于扩展欧几里德(ex

POJ2115——C Looooops(扩展欧几里德+求解模线性方程)

C Looooops DescriptionA Compiler Mystery: We are given a C-language style for loop of type for (variable = A; variable != B; variable += C) statement;I.e., a loop which starts by setting variable to value A and while variable is not equal to B, repea

poj2115 C Looooops——扩展欧几里得

题目:http://poj.org/problem?id=2115 就是扩展欧几里得呗: 然而忘记除公约数... 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll A,B,C,k,a,b,x,y,g,s; ll gcd(ll a,ll b){return a%b?gcd(b,a%b):b;} void exgc

poj1061——扩展gcd水题

poj1061——扩展gcd水题 青蛙的约会 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 94176   Accepted: 17413 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉

HDOJ 2769 Disgruntled Judge 扩展GCD

扩展GCD: 枚举a,扩展GCD求b,再暴力检查 Disgruntled Judge Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 329    Accepted Submission(s): 142 Problem Description Once upon a time, there was an nwerc judge with

POJ 2115 C Looooops(扩展欧几里得应用)

题目地址:POJ 2115 水题..公式很好推.最直接的公式就是a+n*c==b+m*2^k.然后可以变形为模线性方程的样子,就是 n*c+m*2^k==b-a.即求n*c==(b-a)mod(2^k)的最小解.(真搞不懂为什么训练的时候好多人把青蛙的约会都给做出来了,这题却一直做不出来.....这两道不都是推公式然后变形吗.....) 代码如下: #include <iostream> #include <cstdio> #include <string> #incl

2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余 扩展gcd)

题目链接 分析:打表以后就能发现时卡特兰数, 但是有除法取余. f[i] = f[i-1]*(4*i - 2)/(i+1); 看了一下网上的题解,照着题解写了下面的代码,不过还是不明白,为什么用扩展gcd, 不是用逆元吗.. 网上还有别人的解释,没看懂,贴一下: (a / b) % m = ( a % (m*b)) / b 笔者注:鉴于ACM题目特别喜欢M=1000000007,为质数: 当gcd(b,m) = 1, 有性质: (a/b)%m = (a*b^-1)%m, 其中b^-1是b模m的逆

扩展gcd codevs 1200 同余方程

codevs 1200 同余方程 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 求关于 x 同余方程 ax ≡ 1 (mod b)的最小正整数解. 输入描述 Input Description 输入只有一行,包含两个正整数 a, b,用 一个 空格隔开. 输出描述 Output Description 输出只有一行包含一个正整数x0,即最小正整数解,输入数据保证一定有解. 样例输入 Sa

poj 2891 Strange Way to Express Integers (扩展gcd)

题目链接 题意:给k对数,每对ai, ri.求一个最小的m值,令m%ai = ri; 分析:由于ai并不是两两互质的, 所以不能用中国剩余定理. 只能两个两个的求. a1*x+r1=m=a2*y+r2联立得:a1*x-a2*y=r2-r1;设r=r2-r2; 互质的模线性方程组m=r[i](mod a[i]).两个方程可以合并为一个,新的a1为lcm(a1,a2), 新的r为关于当前两个方程的解m,然后再和下一个方程合并--.(r2-r1)不能被gcd(a1,a2)整除时无解. 怎么推出的看了好