zoukankan      html  css  js  c++  java
  • LightOj 1245 --- Harmonic Number (II)找规律

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1245

    题意就是求 n/i (1<=i<=n) 的取整的和这就是到找规律的题,

    i     1  2   3   4   5   6   7    8 

    a    8  4   2   2   1   1   1    1

    你可以多写几组你会发现

    有8-4个1;4-2个2;。。。其他例子也是这样;

    当n = 10时

    n/1 = 10, n/2 = 5说明(5, 10]这个前开后闭的区间中对应的结果都是 1 ,共有10-5 = 5个 ans += 5*1;

    n/2 = 5, n/3 = 3说明(3, 5]这个前开后闭的区间中对应的结果都是 2 ,共有5-3 = 2个  ans += 2*2;

    n/3 = 3, n/4 = 2说明(2, 3]这个前开后闭的区间中对应的结果都是 3 ,共有3-2 = 1个  ans += 1*3;

    n/4 = 2, n/5 = 2说明(2, 2]这个前开后闭的区间中对应的结果都是 4 ,共有2-2 = 0个  ans += 0*4;

    n/5 = 2, n/6 = 1说明(1, 2]这个前开后闭的区间中对应的结果都是 5 ,共有2-1 = 1个  ans += 1*5;

    对于一个比较大的数n,直接循环一定会错,所以要优化,对于 1 - (int)sqrt(n)所对应的另一半即[n/(int)sqrt(n), n/1]这些数一定只出现了一次,所以加上,剩下的那些就是出现多次的了,按照规律进行处理,注意会加多的那个部分;

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    #define N 20100
    
    int main()
    {
        int T, n,t=1;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d", &n);
            int i=1, cnt=0;
            long long ans=0;
            if(n==1)
            {
                printf("Case %d: 1
    ", t++);
                continue;
            }
            while(1)
            {
                int a=n/i;
                int b=n/(i+1);
                ans=ans+a+(a-b)*i;///结果;
                cnt=cnt+(a-b)+1;///表示已经加了几个数了;
                i++;
                if(cnt==n-1)///当还剩一个数时就结束就行了,并且还要把这个数加上;
                {
                    ans+=n/i;
                    break;
                }
                if(b<=i)///当后面那个数<=i事就说明已经加完了;
                    break;
            }
            printf("Case %d: %lld
    ", t++, ans);
        }
        return 0;
    }
    View Code

    简单的写法

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <vector>
    #include <math.h>
    using namespace std;
    typedef long long LL;
    const int oo = 0xfffffff;
    const int N = 1e7+1;
    const double eps = 1e-8;
    
    int main()
    {
        int T, t = 1;
    
        scanf("%d", &T);
    
        while(T--)
        {
            LL n;
    
            scanf("%lld", &n);
    
            LL ans = 0, a = 0, b = 0, k = (int)sqrt(n);
    
            for(int i=1; i<=k; i++)
            {
                a = n/i, b = n/(i+1);
                ans += a + (a-b)*i;
            }
            if(k == n/k)
                ans -= k;
            printf("Case %d: %lld
    ", t++, ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ubuntu 安装 Java 开发环境
    mtd-utils 的 使用
    容器技术与虚拟化技术
    Shell之作业控制
    Shell常用语句及结构
    Shell常用命令之read
    Shell之函数
    文件的copy
    类中调用初始化方法
    父类中的方法被覆盖以及子类调用父类覆盖的方法
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4947462.html
Copyright © 2011-2022 走看看