zoukankan      html  css  js  c++  java
  • NYOJ 954

    首先观察:

    2! = 2×1                 = (2)10     = (10)2,          则第一个1是第2位,2!有1个质因数2
    3! = 3×2×1             = (6)10     = (110)2,        则第一个1是第2位,3!有1个质因数2
    4! = 4×3×2×1         = (24)10   = (11000)2,        则第一个1是第4位,4!有3个质因数2
    5! = 5×4×3×2×1     = (120)10 = (1111000)2,     则第一个1是第4位,5!有3个质因数2
    6! = 6×5×4×3×2×1 = (720)10 = (1011010000)2,则第一个1是第5位,  6!有4个质因数3

    ...

    这时候规律就很明显了,就是有n个质因数2的话,就会在二进制形式下后面跟n个0,则所求答案就是n+1,即在n+1位上出现第一个1.  

    这时候一个很朴素的思路是,测试n!的每个因子的质因数2的个数,然后加起来就好了。

    代码如下:

     1 #include <iostream>
     2 using namespace std;
     3   
     4 int main(){
     5     long long n;
     6     while(cin>>n){
     7         long long res = 1;
     8         for(long long i=1;i<=n;i++){
     9             long long temp = i;
    10             while(temp%2==0){
    11                 res++; 
    12                 temp/=2;
    13             }
    14         }
    15         cout<<res<<endl;
    16     }
    17     
    18     return 0; 
    19 }
    20         
    View Code

    此时复杂度为O(nlnn).  提交显示超时。

    如何改进呢?

    在二进制的形式下,每一位都有1/0两种填充方式,由于计算的是n!,所以这种“填充”是连续的,也就是说在*****0的基础上除以2(即右移一位)得到的就是该位的质因数2 的个数,只需要将这个过程一直做下去直到右移到位数为0即可。

    代码如下:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int main(){
     5     int n;
     6     long long ans;
     7     while(scanf("%d",&n)!=EOF){
     8         ans=0;
     9         while(n){
    10             ans+=n>>1;  
    11             n=n>>1; 
    12         }
    13         printf("%lld
    ",ans+1);
    14     }
    15     return 0;
    16 }
    View Code

    此时复杂度为O(lnn),可ac.

  • 相关阅读:
    关于医学的一点想法
    我的ArcGis9.3 到Arcgis10.0 升级步骤
    最近一月的娱乐生活:看电影,玩游戏
    最近一月的娱乐生活:看电影,玩游戏
    5年技术学习历程的回顾
    5年技术学习历程的回顾
    网站开发的技术选型问题
    网站开发的技术选型问题
    学技术真累
    Java实现 LeetCode 200 岛屿数量
  • 原文地址:https://www.cnblogs.com/liugl7/p/6253381.html
Copyright © 2011-2022 走看看