zoukankan      html  css  js  c++  java
  • hdu--2522--循环节

    这题 还是靠caicai过的 因为他写过一篇 关于这个的博客 当时 没好好的去看它~~

    主要 我一开始自己没做出来 因为有个很重要的定理不知道---当在小数部分出现相同余数 就证明出现循环节了

    因为不知道这个 我就一直纠结怎么判断循环节...

    然后就是模拟 除法 进行运算了 *10 /x   *10 & x

    看下这篇文章 caicai推的 的确不错~    传送

    一般 写的都是用hash记录余数 判断是否重复出现  这样会多开个数组  那里介绍的方法更好

    贴下caicai的代码 还有我根据它修改后 适用于本题的 但他的更能适应于一般所有情况

     1 #include <iostream>
     2 #include <cmath>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 int lowbit( int n )
     7 {
     8     return n & -n;
     9 }
    10 
    11 int main()
    12 {
    13     cin.sync_with_stdio(false);
    14     int n , x , val , num , num2 , num5 , left , mmax;
    15     while( cin >> n )
    16     {
    17         while(n--)
    18         {
    19             num5 = 0;
    20             cin >> x;
    21             if(x<0)
    22             {
    23                 x = -x;
    24                 cout << "-";
    25             }
    26             num = 1 % x;
    27             val = x;
    28             if( x==1 )
    29             {
    30                 cout << "1" << endl;
    31                 continue;
    32             }
    33             else
    34             {
    35                 cout << "0.";
    36             }
    37             num2 = (int)log2( lowbit(x) );
    38             while( val%5 == 0 )
    39             {
    40                 num5++;
    41                 val /= 5;
    42             }
    43             mmax = max( num2 , num5 );
    44             while( mmax-- )
    45             {
    46                 cout << num * 10 /  x;
    47                 num = num * 10 % x;
    48             }
    49             left = num;
    50             while( num )
    51             {
    52                 cout << num * 10 / x;
    53                 num = num * 10 % x;
    54                 if( num == left )
    55                 {
    56                     break;
    57                 }
    58             }
    59             cout << endl;
    60         }
    61     }
    62     return 0;
    63 }
    View Code
     1 #include<iostream>
     2 #include<map>
     3 #include<cmath>
     4 using namespace std;
     5 
     6 int gcd(int x, int y)
     7 {
     8     return y == 0 ? x : gcd(y, x % y);
     9 }
    10 
    11 int main()
    12 {
    13     int x, y, tmp;
    14     while(~scanf("%d%d", &x, &y))
    15     {
    16         int div = gcd(x, y);
    17         x /= div;  // 例如4/24要转化成1/6,不然的话会对后面分母计算2与5的因子数有干扰
    18         y /= div;
    19         int num = x % y;
    20         printf("%d.", x / y); // 首先输出整数部分
    21         if(x % y == 0) // 若是4/2则没必要计算,直接输出结果
    22         {
    23             printf("0
    ");
    24             continue;
    25         }
    26         int aa, bb = 0, tmp = y;
    27         aa = (int)log2((tmp & (-tmp)));  // 计算分母中质因数2的个数,这里用了个小技巧
    28         while(tmp % 5 == 0)  // 计算分母中质因数5的个数
    29         {
    30             bb++;
    31             tmp /= 5;
    32         }
    33         aa = aa > bb ? aa : bb;  // 质因数2和5的数量谁多,循环节就从几位开始,例如45/56,aa=3
    34         while(aa--)  // 前几位小数不算在循环节内,直接输出
    35         {
    36             printf("%d", int(num * 10 / y));
    37             num = num * 10 % y;
    38         }
    39         bb = num; // 循环节开始时的余数,第二个循环节头,即循环结束位置,应与此余数相同
    40         if(num)  // 需要判断当前余数是否为零,否则某些输出的末尾会带有(0)导致输出格式问题
    41         {
    42             printf("(");
    43             printf("%d", int(num * 10 / y));
    44             num = num * 10 % y; // 这两句不可少,若为1/3,则结果为没有前置小数的一位循环节0.(3),需特殊处理
    45             while(num != bb)
    46             {
    47                 printf("%d", int(num * 10 / y));
    48                 num = num * 10 % y;
    49             }
    50             printf(")");
    51         }
    52         printf("
    ");
    53     }
    54     return 0;
    55 }
    View Code

    顺便 提下 对于一个数中含有多少个2的计算  x & -x 可以这样理解

    假如X=24 11000  因为我们可以计算得到从右往左数 第一个 1 的位置及它代表的值 这边就是8了嘛

    我们可以这样看 24 = 8 * ( 1 + 2 ) 这样你就能发现 因为第一个8提供了括号中的一个1 导致后面的数肯定是奇数 那么这个数它所有的2的个数 就肯定由第一个 1 出现的位置的值来决定了

    至于 奇数 就更简单了 因为 由二进制表示的数如果原来是奇数 那么它的第一位 肯定是1  2^0*1 = 1这样 就2的个数是0了 通过log2(x&-x)来计算

    这个x & -x其实就是lowbit(x)在 树状数组的时候 我们也用到了

    ---尽扯了些没用的 =-=

    today:

      恐惧来源于自身 而于外界无关 来源于内心

    just follow your heart
  • 相关阅读:
    控制TABLE的一些属性
    windows7中各个dll文件作用和用途
    left join on and与left join on where的区别
    号外,left join比连表语句快80倍
    JS跳转语句
    [jQuery,Dojo,MooTools]
    CYQ.Data 数据框架 V3.5 开源版本发布(源码提供下载)
    Scala开发小小总结
    性能测试工具原理与架构
    joomla1.5模块开发和插件开发详解带实例
  • 原文地址:https://www.cnblogs.com/radical/p/3871493.html
Copyright © 2011-2022 走看看