好题,好解。
//这道题就是求一个分数的2进制小数的循环节长度和起始位置。
// 首先,先对该分数 n/m 化简。
// n = n / gcd(n, m)
// m = m / gcd(n, m)
// n = n mod m
// 接下来就是需要知道一个分数化成k进制小数的方法:
// for i = 0 to 需要的位数
// n = n * k;
// bit[i] = n / m;
// n = n mod m;
// 可以知道对于某一位的n,设为ni,当到了某一位nj,有ni mod m== nj mod m 时,此时循环节就出现了,长度L = j - i。
// 而aj = (ai * 2 ^ L) mod m 可得 2 ^ L mod m == 1 mod m 。
// 当m与2互质时,由于2 ^ 0 == 1 mod m,2 ^ phi(m) == 1 mod m,循环节的起始点一定为0,即答案的1。
// .而这里m与2不一定互质,可以通过两边同时消去2的t次幂来达到这个条件,即2 ^ (L - t) == 1 mod (m / 2 ^ t)。
// 可见此时循环节起始点为t,即答案为t + 1。
// 剩下的就是求2 ^ L' = 1 mod m' 了,由于若2 ^ k == 1 mod m',则k整除phi(m'),所以我们可以从小到大枚举phi(m')的因子,即可得到答案。
//============================================================================
// Name : 3358.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
//这道题就是求一个分数的2进制小数的循环节长度和起始位置。
// 首先,先对该分数 n/m 化简。
// n = n / gcd(n, m)
// m = m / gcd(n, m)
// n = n mod m
// 接下来就是需要知道一个分数化成k进制小数的方法:
// for i = 0 to 需要的位数
// n = n * k;
// bit[i] = n / m;
// n = n mod m;
// 可以知道对于某一位的n,设为ni,当到了某一位nj,有ni mod m== nj mod m 时,此时循环节就出现了,长度L = j - i。
// 而aj = (ai * 2 ^ L) mod m 可得 2 ^ L mod m == 1 mod m 。
// 当m与2互质时,由于2 ^ 0 == 1 mod m,2 ^ phi(m) == 1 mod m,循环节的起始点一定为0,即答案的1。
// .而这里m与2不一定互质,可以通过两边同时消去2的t次幂来达到这个条件,即2 ^ (L - t) == 1 mod (m / 2 ^ t)。
// 可见此时循环节起始点为t,即答案为t + 1。
// 剩下的就是求2 ^ L' = 1 mod m' 了,由于若2 ^ k == 1 mod m',则k整除phi(m'),所以我们可以从小到大枚举phi(m')的因子,即可得到答案。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int t, n, m, GCD, phi, ans1, ans2;
int temp, num;
int fac[1000000];
int gcd(int x, int y){
int r;
if(x < y){
swap(x, y);
}
while(x%y){
r = x%y;
x = y;
y = r;
}
return y;
}
int euler(int x){
int y = (int)sqrt(x+0.5);
int curans = x;
for(int i = 2;i <= y;i++){
if(x%i == 0){
curans = curans/i*(i-1);
while(x%i == 0){
x /= i;
}
}
}
if(x > 1){
curans = curans/x*(x-1);
}
return curans;
}
int quickpow(int m, int n, int k){
int b = 1;
while(n > 0){
if(n&1){
b = (long long)b*m%k;
}
n >>= 1;
m = (long long)m*m%k;
}
return b;
}
int main(){
// printf("%d\n", euler(5));
freopen("a.txt", "r", stdin);
int T = 0;
while(scanf("%d/%d", &n, &m)!=EOF){
T++;
GCD = gcd(n, m);
// printf("%d\n", GCD);
n /= GCD;
m /= GCD;
// printf("%d %d\n", n, m);
t = 0;
while(m%2 == 0){
t++;
m /= 2;
}
ans1 = t+1;
phi = euler(m);
if(phi == 1){
ans2 == 1;
}
else{
num = 0;
for(int i = 1;i*i <= phi;i++){
if(phi%i == 0)
{
fac[num++] = i;
fac[num++] = phi/i;
}
}
sort(fac, fac+num);
// printf("%d\n", num);
for(int i = 0;i < num;i++){
// printf("%d\n", fac[i]);
temp = quickpow(2, fac[i], m);
// printf("i: %d phi: %d %d\n", i, phi, temp);
if(temp == 1){
// printf("%d\n\n", ans2);
ans2 = fac[i];
break;
}
}
}
printf("Case #%d: ", T);
printf("%d,%d\n", ans1, ans2);
}
return 0;
}