zoukankan      html  css  js  c++  java
  • xdoj--1077: (循环节长度)

    1077: 循环节长度

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 103  解决: 37
    [提交][状态][讨论版]

    题目描述

    数一有很多的有理数,然而有的是有限小数,如1/2=0.5,1/5=0.2,这些都很好写,但是对于无限循环小数,数一就发愁了,怎么写得完啊。于是数一就想让你告诉他这些有理数的循环节长度是多少。

    输入

    多组数据,每组数据是两个整数p,q(0<=p<10^9,0<q<=10^9),表示一个有理数的分子与分母。

    输出

    若为有限小数,则输出0,若为无限循环小数,请输出循环节长度。

    样例输入

    1 2
    1 3
    2 10
    2 7
    5 6

    样例输出

    0 1 0 6 1

    想法:

      1 证明有理数a/b可以写成无限循环小数

       1) 根据抽屉原理 存在10^m%b=10^n%b

          对于任何b存在一个数c (b|c 且c可以写成10^i(10^j-1)的形式 )

     2)a/b=d/c [ d=a*c/b   则d是整数 ]=(d/10^i) * ( 1/(10^j-1) )

     3)   x=  1/(10^j-1)  一定是有理小数并且循环节长度为j

      方法

      1  用bsgs 求解(10^j%b=1)

       2 用数组实现hash

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int mod=774321;
     5 struct node {
     6     int k1,k2;
     7     int _next;    
     8 };
     9 int hs[mod+7];
    10 node hn[mod+7]; int cnt;
    11 int gcd (int x,int y) {
    12     return !y?x:gcd(y,x%y);
    13 }
    14 void  _add (int x, int key) {
    15     int head=x%mod;
    16     hn[++cnt].k2=key; hn[cnt].k1=x;
    17     hn[cnt]._next=hs[head];
    18     hs[head]=cnt;
    19 }
    20 int _find (int x) {
    21     int head=x%mod;
    22     for (int i=hs[head];i!=-1;i=hn[i]._next) {
    23         if (hn[i].k1==x)
    24             return hn[i].k2;
    25     }
    26     return -1;
    27 }
    28 int bsgs (int k,int p) { 
    29     cnt=0; memset (hs,-1,sizeof(hs));
    30     LL x=1; int t=sqrt(p)+1;  
    31     for (int i=0;i<t;i++) {
    32         _add (x,i);
    33         x=x*k%p;
    34     }
    35     LL y=1; 
    36     for (int i=1;i<=t;i++) {
    37         y=y*x%p;  // 不使用long long 会溢出
    38         int ans=_find(y);
    39         if (ans>=0)  return i*t-ans;
    40     }
    41 }
    42 int main ()
    43 {
    44     int a,b; 
    45     while ( ~scanf ("%d %d",&a,&b) ) {
    46         int k=gcd (a,b); a/=k; b/=k;
    47         while (b%2==0) b/=2;
    48         while (b%5==0) b/=5;
    49         if (b==1) printf("0
    ");
    50         else      printf("%d
    ",bsgs(10,b) );
    51     }
    52     return 0;
    53 }
    抓住青春的尾巴。。。
  • 相关阅读:
    bean的注入方式
    Spring中的IOC
    BeanFactory和ApplicationContext的区别
    mysql出现锁表 com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
    centos防火墙
    sql中union和union all的区别
    Sql语句中IN和exists的区别及应用
    ROLLUP,CUBE,GROUPPING详解
    通过WinRM在本机执行云服务器脚本,更新git代码
    Sqlserver2012评估期已过问题解决
  • 原文地址:https://www.cnblogs.com/xidian-mao/p/9605840.html
Copyright © 2011-2022 走看看