1 条题解
-
0
题解思路:有理数二进制小数的最小周期
这个问题要求我们找到一个有理数的小数部分在二进制表示下的最小周期及其起始位置。解决这个问题需要结合数论和位运算的知识,下面详细解释解题思路。
代码实现分析
下面是代码的关键部分分析:
// 计算最大公约数 int gcd( int a , int b ) { return b == 0 ? a : gcd( b , a % b ); } // 计算欧拉函数 int euler(int n) { int ret=1,i; for (i=2;i*i<=n;i++) if (n%i==0) { n/=i,ret*=i-1; while (n%i==0) n/=i,ret*=i; } if (n>1) ret*=n-1; return ret; } // 快速幂取模 int Pow( int a , int b , int c ) { int ans = 1 ; while( b > 0 ) { if( b & 1 ) { ans = ( long long ) ans * a % c ; } b >>= 1 ; a = ( long long )a * a % c ; } return ans ; } int main() { int Case = 1 ; while( scanf( "%d/%d" , &n , &m ) != EOF ) { // 约分处理 GCD = gcd( n , m ) ; n /= GCD ; m /= GCD ; // 分离2的幂次 t = 0 ; while( m % 2 == 0 ) { t++ ; m /= 2 ; } ans1 = t + 1 ; // 起始位置 // 计算欧拉函数 phi = euler( m ) ; // 寻找最小周期 if( phi == 1 ) { ans2 = 1 ; } else { int num = 0 ; // 枚举phi的所有因数 for( int i = 1 ; i * i <= phi ; ++i ) { if( phi % i == 0 ) { fac[ num++ ] = i ; fac[ num++ ] = phi / i ; } } sort( fac , fac + num ) ; // 找到最小的s使得2^s ≡1 mod m for( int i = 0 ; i < num ; ++i ) { temp = Pow( 2 , fac[ i ] , m ) ; if( temp == 1 ) { ans2 = fac[ i ] ; break ; } } } printf( "Case #%d: %d,%d\n" , Case++ , ans1 , ans2 ) ; } return 0 ; }
关键点总结
- 约分处理:确保分子和分母互质,简化后续计算。
- 2的幂次分离:确定非循环部分长度。
- 欧拉函数应用:利用数论知识找到可能的周期候选。
- 快速幂取模:高效计算大数幂的模运算。
通过这些步骤,我们可以高效地找到有理数二进制表示的最小周期及其起始位置。
- 1
信息
- ID
- 2359
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者