poj3358 Period of an Infinite Binary Expansion

首先要明确分式的二进制表达方式:

1 //supposing the fraction is a / b, (a < b && (a, b))
2 //its binary expression is denoted as : 0.bit[1]bit[2]...
3 seed[0] = a;
4 for(int i = 1; ; i++){ 5 bit[i] = (seed[i - 1] << 1) / b; 6 seed[i] = (seed[i - 1] << 1) % b;
7 }

不妨设其中一个循环节为bit[r]..bit[s],显然有seed[r - 1] = seed[s] 且bit[r] = bit[s + 1],其中循环节长度l = (s - r + 1)。

由seed[i] = 2i+1 % b, 则有 2r  % b = 2s+1 % b,  即2r(2s-r+1-1) ≡ 0(modb),

记b = 2t*b1,其中 (b1,2),且令r = t,则 2l≡ 1(modb1)。

则l|φ(b1),由此枚举b1的约数即可得到周期l。

并且有初始位置p = t + 1 。

http://poj.org/problem?id=3358

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 using namespace std;
 6 typedef __int64 LL;
 7 const int maxn = 1e2 + 10;
 8 int prime[maxn], k;
 9 int fac[maxn];
10 int a, b, B;
11 
12 int power(int a, int p){
13     a %= B;
14     int ans = 1;
15     while(p){
16         if(p & 1) ans = (LL)ans * a % B;
17         p >>= 1;
18         a = (LL)a * a % B;
19     }
20     return ans;
21 }
22 
23 int gcd(int a, int b) { return !b ? a : gcd(b, a % b); }
24 
25 void solve(){
26     a %= b;
27     int d = gcd(a, b);
28     a /= d, b /= d;
29     int t = 0;
30     while(b % 2 == 0) b /= 2, ++t;
31     printf("%d,", ++t);
32     if(b == 1) { printf("%d
",1); return; }
33     k = 0;
34     B = b;
35     int phi = b;
36     int mid = (int)sqrt(b);
37     for(int i = 3; i <= mid; i += 2){
38         if(b % i == 0){
39             prime[k++] = i;
40             while(b % i == 0) b /= i;
41          }
42     }
43     if(b != 1) prime[k++] = b;
44     for(int i = 0; i < k; i++) phi /= prime[i];
45     for(int i = 0; i < k; i++) phi *= (prime[i] - 1);
46     k = 0;
47     for(int i = 1; i * i <= phi; i++){
48         if(phi % i == 0) fac[k++] = i, fac[k++] = phi / i;
49     }
50     sort(fac, fac + k);
51     for(int i = 0; i < k; i++) if(power(2, fac[i]) == 1){
52         printf("%d
", fac[i]);
53         break;
54     }
55 }
56 
57 int main(){
58     //freopen("in.txt", "r", stdin);
59     int kase = 0;
60     while(~scanf("%d/%d", &a, &b)){
61         printf("Case #%d: ", ++kase);
62         solve();
63     }
64     return 0;
65 }
View Code
原文地址:https://www.cnblogs.com/astoninfer/p/4807999.html