poj 3358 Period of an Infinite Binary Expansion(欧拉函数+欧拉定理)

12 篇文章 0 订阅
Period of an Infinite Binary Expansion
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 2769 Accepted: 718

Description

Let {x} = 0.a1a2a3... be the binary representation of the fractional part of a rational number z. Suppose that {x} is periodic then, we can write

{x} = 0.a1a2...ar(ar+1ar+2...ar+s)w

for some integers r and s with r ≥ 0 and s > 0. Also, (ar+1ar+2...ar+s)wdenotes a nonterminating and repeating binary subsequence of {x}.

The subsequence x1 = a1a2 ... aris called the preperiod of {x} and x2 = ar+1ar+2 ... ar+s is the period of {x}.

Suppose that |x1| and |x2| are chosen as small as possible then x1 is called the least preperiod and x2 is called the least period of {x}.

For example, x = 1/10 = 0.0001100110011(00110011)w and 0001100110011 is a preperiod and 00110011 is a period of 1/10.

However, we can write 1/10 also as 1/10 = 0.0(0011)w and 0 is the least preperiod and 0011 is the least period of 1/10.

The least period of 1/10 starts at the 2nd bit to the right of the binary point and the the length of the least period is 4.

Write a program that finds the position of the first bit of the least period and the length of the least period where the preperiod is also the minimum of a positive rational number less than 1.

Input

Each line is test case. It represents a rational number p/q where p and q are integers, p ≥ 0 and q > 0.

Output

Each line corresponds to a single test case. It represents a pair where the first number is the position of the first bit of the least period and the the second number is the length of the least period of the rational number.

Sample Input

1/10 
1/5 
101/120 
121/1472

Sample Output

Case #1: 2,4 
Case #2: 1,4 
Case #3: 4,4 
Case #4: 7,11
 
 
题意:给出小数p/q的十进制表示,求当p/q的结果化为二进制的小数时,使p/q的循环节和非循环节都最短时,循环节开始的位置和循环节的长度。
思路:以下的discuss的做法:
我们可以观察一下1/10这组数据,按照二进制转换法(乘二法),我们可以得到:
1/10  2/10 4/10 8/10 16/10 32/10 ...
然后都分子都尽可能减去10,得到:
1/10  2/10 4/10 8/10 6/10 2/10 ...
这时候,发现出现了重复,那么这个重复就是我们要求的最小循环。
抽象出模型如下:对p/q首先p'=p/gcd(p,q)q'=q/gcd(p,q) (即化为最简);
然后我们就是求p'*2^i == p'*2^j (mod q')   (“==”表示同余,i<j)
经过变换得到:p'*2^i*(2^(j-i)-1) ==0 (mod q')也就是 q' | p'*2^i*(2^(j-i)-1)
由于gcd(p',q')=1,得到: q' | 2^i*(2^(j-i)-1)
因为2^(j-i)-1为奇数,所以q'有多少个2的幂,i就是多少,而且i就是循环开始位置的前一位。
那么令q''为q'除去2的幂之后的数此时 q'' | 2^(j-i)-1也就是求出x,使得 2^x ==1 (mod q'')
而根据欧拉定理,a^{\varphi(n)} \equiv 1 \pmod nφ(n)为n的欧拉函数,那么我们要求出的x即为φ(n)的满足2^x%q''=1的最小因子。
 
AC代码:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <queue>
#include <ctime>
#include <algorithm>

#define ll __int64

using namespace std;

int fac[100005];
int cnt;
int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a % b);
}
int euler(int n)
{
    int ret = n;
    for(int i = 2; i * i <= n; i++)
    if(n % i == 0)
    {
        ret = ret / i * (i - 1);
        while(n % i == 0) n /= i;
    }
    if(n > 1) ret = ret / n * (n - 1);
    return ret;
}
void get_factor(int n)
{
    cnt = 0;
    for(int i = 1; i * i <= n; i++)
    if(n % i == 0)
    {
        fac[cnt++] = i;
        fac[cnt++] = n / i;
    }
}
int Montgomery(int a, int b, int m)
{
    int r = 1;
    a %= m;
    while(b)
    {
        if(b & 1) r = (long long) r * a % m;
        a = (long long) a * a % m;
        b >>= 1;
    }
    return r;
}
int main()
{
    int p, q, c = 0;
    int ans1, ans2;
    while(~scanf("%d/%d", &p, &q))
    {
        int GCD = gcd(p, q);
        p /= GCD;
        q /= GCD;
        ans1 = 0;
        while(q % 2 == 0)
        {
            ans1++;
            q /= 2;
        }
        int phi = euler(q);
        get_factor(phi);
        sort(fac, fac + cnt);

        for(int i = 0; i <cnt; i++)
        if(Montgomery(2, fac[i], q) == 1)
        {
            ans2 = fac[i];
            break;
        }
        printf("Case #%d: %d,%d\n", ++c, ans1 + 1, ans2);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值