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

分析:设对于某组数据要循环x次结束,可得方程:

x=[(B-A+2^k)%2^k]/C

即 Cx=(B-A)(mod 2^k)  此方程为 模线性方程,本题就是求x的值。

即求模线性方程 ax=b mod n的解。 其中a=C,b=B-A,n=2^K.

该方程有解的充要条件为 gcd(a,n) | b ,即 b% gcd(a,n)==0

令d=gcd(a,n)有该方程的 最小整数解为 x0 = X (mod n/d)

X为任意解,x0为最小整数解

#include<stdio.h>
__int64 exgcd(__int64 a,__int64 b,__int64 &x,__int64 &y)  //扩展欧几里得
{
    __int64 t,d;
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    d=exgcd(b,a%b,x,y);
    t=x;
    x=y;
    y=t-a/b*y;
    return d;
}
int main()
{
    __int64 A,B,C,k,a,b,n,d,x,y;
    while(scanf("%I64d%I64d%I64d%I64d",&A,&B,&C,&k)!=EOF){
        if(A==0&&B==0&&C==0&&k==0)
            break;
        a=C;
        b=B-A;
        n=(__int64)1<<k;  //1要转化为64位
        d=exgcd(a,n,x,y);
        if(b%d){         //若方程无解,则会一直循环
            printf("FOREVER\n");
            continue;
        }
        x=x*(b/d)%n;
        x=(x%(n/d)+(n/d))%(n/d); //求最小正解
        printf("%I64d\n",x);
    }
    return 0;
}
时间: 2024-10-13 16:05:41

poj 2115 C Looooops (解模线性方程)的相关文章

POJ 2115 C Looooops(模线性方程)

http://poj.org/problem?id=2115 题意: 给你一个变量,变量初始值a,终止值b,每循环一遍加c,问一共循环几遍终止,结果mod2^k.如果无法终止则输出FOREVER. 思路: 根据题意原题可化成c * x = b - a mod (2 ^ k),然后解这个模线性方程. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio>

poj 2947 Widget Factory (高斯消元,解模线性方程)

链接:poj 2947 题意:生产一些零件,已知零件种数,记录条数 记录只记录了某次生产从周几开始,周几结束,以及生产了哪些产品. 每件商品生产所需天数为3-9天. 求每样产品需要多少天才能完成. 若无解输出Inconsistent data. 有无穷解输出Multiple solutions. 有唯一解,输出其解 分析:根据题目所给信息,可以列出同余方程组,再根据高斯消元求解, 但还得判断是无解,无穷解,还是唯一解 1.系数矩阵的秩若与增广矩阵的秩不相等,则无解,否则有解 2.若有解,若增广矩

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(Exgcd)

[题目链接] http://poj.org/problem?id=2115 [题目大意] 求for (variable = A; variable != B; variable += C)的循环次数, 其中变量为k比特无符号整数. [题解] 题目等价于求解Cx=(B–A)(mod 2^k),利用扩展欧几里得算法可以求解该问题 [代码] #include <algorithm> #include <cstring> #include <cstdio> using name

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 (线性同余方程)

C Looooops Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19141   Accepted: 5049 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 (扩展欧几里得)

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

辗转相除法(欧几里得算法) 时间复杂度:在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: 18799   Accepted: 4924 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