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

至于扩欧……看了好久。。。

http://blog.csdn.net/zhjchengfeng5/article/details/7786595

http://www.matrix67.com/blog/archives/5100

这俩博客挺不错的

代码如下:

#include <cstdio>

using namespace std;
#define ll long long

ll e_gcd(ll a,ll b,ll &x,ll &y)//递归扩欧
{
    if(!b)
    {
        x = 1;
        y = 0;
        return a;
    }

    ll tmp, ans = e_gcd(b,a%b,x,y);
    tmp = x;
    x = y;
    y = tmp - a/b*y;
    return ans;
}

ll cal(ll a,ll m,ll c)//求逆元
{
    ll x,y,gcd;
    gcd = e_gcd(a,m,x,y);
    if(c%gcd != 0) return -1;//不可余说明方程无解 即为FOREVER
	 x=(x*(c/gcd))%m;
    x=(x%(m/gcd)+m/gcd)%(m/gcd);//约分求最小解
    return x;
}

int main()
{
    int i,k;
    ll a,b,c,cnt;

    while(~scanf("%lld %lld %lld %d",&a,&b,&c,&k) && k)
    {
        cnt = cal(c,1LL<<k,b-a);
        if(cnt == -1) puts("FOREVER");
        else printf("%lld\n",cnt);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-20 19:46:50

【POJ 2115】 C Looooops (扩展欧几里德)的相关文章

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*

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

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 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

poj 2115 C Looooops (解模线性方程)

链接:poj 2115 题意:对于C语言的循环语句for(i=A ; i!=B ;i +=C), 问在k位存储系统中循环几次才会结束. 若在有限次内结束,则输出循环次数,否则输出死循环. 注:利用了 k位存储系统的数据特性进行循环(会溢出) 例如int型是16位的,那么int能保存2^16个数据, 即最大数为65535(本题默认为无符号), 当循环使得i超过65535时,则i会返回0重新开始计数 如i=65534,当i+=3时,i=1   即 i=(65534+3)%(2^16)=1 分析:设对

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

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

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

poj 2115 C Looooops(推公式+扩展欧几里得模板)

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 statem