C Looooops(扩展欧几里德)

C Looooops

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 10   Accepted Submission(s) : 3

Problem 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

题解:

输出lld老是wa,改成I64就过了。。。还有(LL)1<<k,也要加LL,否则还会wa

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
typedef long long LL;
void e_gcd(LL a,LL b,LL &d,LL &x,LL &y){
    if(!b){
        d=a;
        x=1;
        y=0;
    }
    else{
        e_gcd(b,a%b,d,x,y);
        LL temp=x;
        x=y;
        y=temp-a/b*y;
    }
}
void cal(LL a,LL b,LL c){
    LL d,x,y;
    e_gcd(a,b,d,x,y);
    if(c%d!=0){
        puts("FOREVER");
        return;
    }
    x*=c/d;
    b/=d;
    if(b<0)b=-b;
     x%=b;
    if(x<0)x+=b;
    printf("%I64d\n",x);
    return;
}
int main(){
    LL A,B,C,k;
    while(~scanf("%lld%lld%lld%lld",&A,&B,&C,&k),A|B|C|k){
        //C*x+2^ky=B-A;
        cal(C,(LL)1<<k,B-A);
    }
    return 0;
}
时间: 2024-08-26 03:43:00

C Looooops(扩展欧几里德)的相关文章

POJ 2115-C Looooops(扩展欧几里德)

C Looooops Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17981   Accepted: 4694 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 w

poj2115-C Looooops(扩展欧几里德算法)

本题和poj1061青蛙问题同属一类,都运用到扩展欧几里德算法,可以参考poj1061,解题思路步骤基本都一样.一,题意: 对于for(i=A ; i!=B ;i+=C)循环语句,问在k位存储系统中循环几次才会结束. 比如:当k=4时,存储的数 i 在0-15之间循环.(本题默认为无符号) 若在有限次内结束,则输出循环次数. 否则输出死循环.二,思路: 本题利用扩展欧几里德算法求线性同余方程,设循环次数为 x ,则解方程 (A + C*x) % 2^k = B ;求出最小正整数 x. 1,化简方

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

【POJ 2115】 C Looooops (扩展欧几里德)

[POJ 2115] C Looooops 输入四个数a b c k 一个循环for(a;;a += c) if(a == b) break; a在k进制内循环 即0 <= a < 2^k 如果超了就返回0 即始终对2^k取余 可以得到一个方程 满足题意的话 a+c*x = b(mod 2^k) 即 c*x = b(mod 2^k) + a = (b+a)(mod 2^k) 同余 就变成求c跟2^k的逆元了 跑一遍扩欧即可 注意要变换成求最小正解 普通扩欧只是求个解 至于扩欧--看了好久...

POJ 2115 C Looooops (扩展欧几里德 + 线性同余方程)

分析:这个题主要考察的是对线性同余方程的理解,根据题目中给出的a,b,c,d,不难的出这样的式子,(a+k*c) % (1<<d) = b; 题目要求我们在有解的情况下求出最小的解,我们转化一下形式. 上式可以用同余方程表示为  a + k*c = (b) % (1<<d)   <-->  k*c = (b-a) % (1<<d)(中间应该是全等号,打不出来…).这就是我们想要的同余方程,根据我的个人习惯,我把它转化为线性方程的形式. -->   c*

扩展欧几里德算法

文章来源:http://blog.csdn.net/zhjchengfeng5/article/details/7786595 谁是欧几里德?自己百度去 先介绍什么叫做欧几里德算法 有两个数 a b,现在,我们要求 a b 的最大公约数,怎么求?枚举他们的因子?不现实,当 a b 很大的时候,枚举显得那么的na?ve ,那怎么做? 欧几里德有个十分又用的定理: gcd(a, b) = gcd(b , a%b) ,这样,我们就可以在几乎是 log 的时间复杂度里求解出来 a 和 b 的最大公约数了

POJ2142 The Balance (扩展欧几里德)

本文为博主原创文章,欢迎转载,请注明出处 www.cnblogs.com/yangyaojia The Balance 题目大意  你有一个天平(天平左右两边都可以放砝码)与重量为a,b(1<=a,b<=10000)的两种砝码.让你求出一种方案称出重为c(1<=c<=50000)的物品,如有多种方案,请输出两种砝码需要数量的总和最小的方案. 输入 有若干行,每行三个数,a,b,c. 结束时用0 0 0表示. 输出 若干行,每行两个数,表示每个询问中a的数量与b的数量 如果无解输出 

欧几里德与扩展欧几里德算法(转)

欧几里德算法 欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数. 基本算法:设a=qb+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd(b,a%b). 第一种证明: a可以表示成a = kb + r,则r = a mod b 假设d是a,b的一个公约数,则有 d|a, d|b,而r = a - kb,因此d|r 因此d是(b,a mod b)的公约数 假设d 是(b,a mod b)的公约数,则 d | b , d |r ,但是a