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_gcd),自己网上学习吧。


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long LL;
LL A,B,C,k,a,b,c,x,y,g;
LL ex_gcd(LL a,LL b,LL &x,LL &y){
	if (!b){
		x=1,y=0;
		return a;
	}
	LL gcd=ex_gcd(b,a%b,y,x);
	y-=(a/b)*x;
	return gcd;
}
int main(){
	while (~scanf("%lld%lld%lld%lld",&A,&B,&C,&k)&&(A||B||C||k)){
		k=1LL<<k;
		//A+xC=B (mod 2^k)
		//Cx+(2^k)y=B-A
		a=C,b=k,c=(B-A+k)%k;
		g=ex_gcd(a,b,x,y);
		if (c%g){
			puts("FOREVER");
			continue;
		}
		a/=g,c/=g,b/=g;
		x*=c,y*=c;
		x=(x%b+b)%b;
		printf("%lld\n",x);
	}
	return 0;
}

  

时间: 2024-08-13 12:04:16

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

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(扩展欧几里德)

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,化简方

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

【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的逆元了 跑一遍扩欧即可 注意要变换成求最小正解 普通扩欧只是求个解 至于扩欧--看了好久...

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

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*

poj2142-The Balance(扩展欧几里德算法)

一,题意: 有两个类型的砝码,质量分别为a,b;现在要求称出质量为d的物品, 要用多少a砝码(x)和多少b砝码(y),使得(x+y)最小.(注意:砝码位置有左右之分). 二,思路: 1,砝码有左右位置之分,应对比两种情况 i,a左b右,得出方程 ax1 - by1 = d ; ii,b左a右,得出方程 bx2 - ay2 = d . 2,利用扩展欧几里德算法,解出(x1,y1).(x2,y2),并求出最小x1和x2,以及相对应的y1,y2. 3,输出x1+y1和x2+y2 中的最小值. 三,步骤

扩展欧几里德算法

文章来源: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 的最大公约数了