zoukankan      html  css  js  c++  java
  • POJ 2115 C Looooops 题解 (数论)

    C Looooops (From http://poj.org/problem?id=2115)
     

    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


    分析:  依题意,要求找到满足 A + Cx = B (mod 2^k) 最小非负整数 x, 即求解模线性方程 Cx = B - A (mod 2^k).
          令 a = C, b = B - A, n = 2^k, 则 方程变为 ax = b (mod n).
          记 d = gcd(a, n), 若 d | b 则方程有解, 否则无解. 无解对应题目中的无限循环(FOREVER).
          
          由数论知识, 存在整数 x', y' 使得 d = ax' + ny'成立, 即 x' 为模线性方程 ax = d (mod n)的一个解.
          则方程 ax = b (mod n) 的一个解为 x0 = x'* b/d, 其解的集合 {x0 + i * (n/d) | i = 0, 1, ..., d-1},
          其中包含了方程对模 n 的 d 个不同的解.
          
          由于 ax = b (mod n), 则存在整数 y 使得 ax + ny = b. 有 a'x + n'y = b',
          其中 a' = a/d, n' = n/d, b' = b/d.
          可知 方程 a'x = b' (mod n') 与方程 ax = b (mod n) 同解.
          由于 gcd(a', n') = 1, 所以对模 n'方程只有一个解.
          则 (x0 mod n' + n') mod n'就是 方程 a'x = b (mod n') 和方程 ax = b (mod n) 的最小非负整数解.
          
          可以利用扩展欧几里得算法求出 x' 和 d, 进而可求出 x0 和最终答案.
          
          可参考《算法导论》第二版第三十一章有关数论的算法。

    源代码
     1 #include <stdio.h>
     2 
     3 typedef long long int int_t;
     4 
     5 int_t EXTENDED_EUCLID(int_t a, int_t b, int_t *px, int_t *py) {
     6     if (b == 0) { *px = 1, *py = 0; return a; }
     7     else {
     8         int_t d, x, y;
     9         d = EXTENDED_EUCLID(b, a % b, &x, &y);
    10         *px = y, *py = x - (a/b)*y;
    11         return d;
    12     }
    13 }
    14 
    15 /**
    16  *    ax = b (mod n); 0=< a < n, |b| < n 
    17  */
    18 int_t MODULAR_LINEAR_EQUATION_SOLVER(int_t a, int_t b, int_t n) { 
    19     int_t x, y, m;
    20     int_t d = EXTENDED_EUCLID(a, n, &x, &y);
    21     if (b % d != 0) {
    22         return -1;
    23     } else {
    24         x = x * b/d;
    25         m = n / d;
    26         return ((x+m)%m+m)%m; // why?
    27     }
    28 }
    29 
    30 int main() {
    31     int_t A, B, C, k;
    32     while (scanf("%lld%lld%lld%lld", &A, &B, &C, &k) != EOF && k != 0) {
    33         int_t x = MODULAR_LINEAR_EQUATION_SOLVER(C, B-A, 1LL << k);
    34         if (x == -1) {
    35             printf("FOREVER
    ");
    36         } else {
    37             printf("%lld
    ", x);
    38         }
    39     }
    40     return 0;
    41 }
           
      


  • 相关阅读:
    DOS下读取4GB内存
    开始了
    PHP函数补完:var_export()
    php 调试相关
    css选择符
    javascript的urlencode
    用CSS代码绘制三角形 纯CSS绘制三角形的代码
    Jquery 操作Cookie
    提高PHP编程效率的53种方法
    执行phpinfo();时提示:date_default_timezone_set()
  • 原文地址:https://www.cnblogs.com/william-cheung/p/3660422.html
Copyright © 2011-2022 走看看