poj2115-Looooops-(扩展欧几里得定理)

C Looooops

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions:33752   Accepted: 9832

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翻译:在循环里,values值为a,每次加c,如果values不等于b,就继续循环下去,死循环输出forever,否则输出循环次数。所有运算都对无符号的k位二进制求模。解题过程:设p=2^k起点为a,每次加c,对p求模若能等于b对p求模则有解,否则无解,输出forever有解的话设解为x(a+cx)%p = b%pa%p + cx%p = b%pcx%p = (b-a)%pcx%p + 0 = (b-a)%pcx%p + yp%p = (b-a)%p形如ax+by=gcd,扩展欧几里得定理。
 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<math.h>
 6 #include<string>
 7 #define ll long long
 8 #define inf 0x3f3f3f3f
 9 using namespace std;
10 // ax + by = gcd(a,b)
11 ll exgcd(ll a, ll b, ll &x, ll &y)//扩展欧几里德定理
12 {
13     if(b==0)//终有一次a%b传进来是0,递归出口
14     {
15         x=1;
16         y=0;
17         return a;
18     }
19     ll q=exgcd(b,a%b,y,x);
20     //最终递归出来,y1=1,x1=0
21     y=y-(a/b)*x;
22     //后面的y相当于下一个递归的x2,x相当于下一个递归的y2,符合推导公式
23     //x1=y2;   y1=x2-[a/b]*y2;
24     return q;
25 }
26
27 int main()
28 {
29     ll a,b,c,k,p,x,y;
30     while(scanf("%lld %lld %lld %lld",&a,&b,&c,&k)!=EOF&&(a+b+c+k))
31     {
32         p=1;
33         for(ll i=1;i<=k;i++)
34             p=p*2;
35         ll gcd=exgcd(c,p,x,y);
36         ll d=b-a;
37         if(d%gcd)
38             printf("FOREVER\n");
39         else
40         {
41             ll  multiple=d/gcd;///倍数
42             p=p/gcd;///通解公式:x=x+b/gcd y=y-a/gcd
43             x=( (x*multiple)%p+p )%p;///求最小正数解
44             printf("%lld\n",x);
45         }
46     }
47     return 0;
48 }

 

 

原文地址:https://www.cnblogs.com/shoulinniao/p/10361943.html

时间: 2024-10-21 04:39:51

poj2115-Looooops-(扩展欧几里得定理)的相关文章

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

扩展欧几里得定理

扩展欧几里得定理,很早之前就接触过,没看懂,放弃了,前些天有个有一个题,用扩展欧几里得定理,我竟然都不知道.决定看一下. 看扩展欧几里得定理的最好地方是用维基百科搜索扩展欧几里得算法 就能搜到 照着上面提供第例子走一遍知道什么意思了. 反正主要就是 ax+by=1(mod n) 的x,y值: 还有就是 ax=b(mod n) 这类题的通用解法: 下面粘上一个例子,看完这个例子你就明白了. poj 1061 青蛙的约会 中文题目,我的最爱. 我们设他们跳的步数为step 那么就可以写出算式 n*s

HDU 2669 Romantic (扩展欧几里得定理)

题目大意:给两个数a和b,找出一组x,y使得a*x + b*y = 1,如果找不出输出sorry   题解:显然是用扩展欧几里得定理求解. 又扩展欧几里得定理有,如果a*x+b*y = d   要使得方程有解必有gcd(a,b)为d的约数. 而此题的d = 1  所以若gcd(a,b)!=1,则应该输出sorry #include <bits/stdc++.h> using namespace std; long long e_gcd(long long a,long long b,long

poj1061-青蛙的约会-(贝祖定理+扩展欧几里得定理+同余定理)

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

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

扩展欧几里得定理总结

拓展欧几里得定理主要用来求解同余线性方程,求逆元等,遇到题目给出形如ax+by==c,要求一组满足要求的x和y时,可以联系扩展欧几里得求解 拓展欧几里得由 gcd(a,b) = gcd(b,a%b) 推出 由于 a*x + b*y == gcd(a,b) 必定有解 所以 b*x + (a%b)*y == gcd(b,a%b) 最终得到ax+by==a*y1+b*(x1-(a/b)*y1) 当x0 y0 是方程的一组解,可以得到所有解的形式满足 x=x0+b/d*t y=y0-a/d*t 当 题目

扩展欧几里得定理基础讲解 代码及证明

知识储备 1 . 朴素欧几里得原理:gcd(a,b) == gcd(b,a % b) 2 . 负数取模:忽略符号返回绝对值就好了 3 . 模数原理:对于整数a,b必然存在整数k使得a % b == a - k * b, 且此时k == a / b向下取整 定理内容 对于正整数a,b,必然存在整数(不一定是正数)x,y, 使得ax+by==gcd(x,y) 证明 (来自SDFZ-SPLI的援助) 把两边同时除以gcd(x,y),由朴素欧几里得定理可以得到恒等式,说明一定存在至少一组解使得$ax+b

扩展欧几里得定理——POJ 1061

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

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

辗转相除法(欧几里得算法) 时间复杂度:在O(logmax(a, b))以内 int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); } 扩展欧几里得算法 时间复杂度和欧几里得算法相同 int extgcd(int a, int b, int& x, int& y) { int d = a; if (b != 0) { d = extgcd(b, a % b, y, x); y -= (a / b) * x;

POJ - 2115C Looooops 扩展欧几里得(做的少了无法一眼看出)

题目大意&&分析: for (variable = A; variable != B; variable += C) statement;这个循环式子表示a+c*n(n为整数)==b是停止循环,题目中要求(a+c*n)%2^k=b时停止循环:所以我们可以得到一个形如ax+by=c的方程式:a+c*n=b+2^k*m:通过移项:c*x-2^k*m=b-a:可以直接套exgcd模板了: 代码: #include <iostream> using namespace std; typ