zoukankan      html  css  js  c++  java
  • 一月17日新生冬季练习赛解题报告B.函数问题

    B题的解题报告非常值得写,其解题思路让人叹为观止,比赛的时候没有一个人ac,其实我想用纯暴力劫一下试试呢,幸好没试,不然会挂的很惨

    题目是这样的:

    B.函数问题
    Time Limit: 1000 MS Memory Limit: 32768 K
    Total Submit: 12 (5 users) Total Accepted: 0 (0 users) Special Judge: No
    Description

    定义一个函数f(x),意思为x%(a*b)==0的a,b对数...如

    f(1)=1:1*1

    f(2)=3:1*1,1*2,2*1

    f(3)=3:1*1,1*3,3*1

    f(4)=6:1*1,1*2,2*1,2*2,1*4,4*1

    .................

    现在输入一个正整数N(N<=10^11)..问f(1)+f(2)+f(3)+f(4)+....f(N)的值...

    Input

    多组输入数据。 

    每组数据输入一个n。

    Output

    每组数据输出问题结果,格式为Case #: ans。

    Sample Input
    1
    3
    6
    10
    15
    21
    28
    Sample Output
    Case 1: 1
    Case 2: 7
    Case 3: 25
    Case 4: 53
    Case 5: 95
    Case 6: 161
    Case 7: 246

    这种题呢,看上去是求每个子问题,然后求和,做的过程你会发现单个子问题是没法全部求出来的,就算求出来也没有数组能够存的下(10^11)  就算存的下光是最后的遍历也会把时间全都用完  所以我们要整体的考虑 f(1)加到f(n)的和  

    那么怎么整体考虑呢?

    我们看一下给的前三组例子:

    f(1)=1:1*1

    f(2)=3:1*1,1*2,2*1

    f(3)=3:1*1,1*3,3*1

    求的是  f(1)+f(2)+f(3)

    对于1 有(1,1) 1/(1*1)=1
    对于2 有(1,1) (1,2) (2,1) 2/(1*1)=2 2/(1*2)=1 2/(2*1)=1
    对于3 有(1,1) (1,3) (3,1) 3/(1*1)=3 3/(1*3)=1 3/(3*1)=1

    我们把每两个相乘的数 左边的看做a 右边的看做 b   把相除的结果看做 c  

    把所有分母都移到右边;

    接下来这一步有些跳跃,需要自己想明白

    那么:f(1)+f(2)+f(3)的问题就可以转换成a*b*c<=3的所有abc的种数

    应用到所有就是  a*b*c<=n的所有abc的组合数  其中abc科翔等或者不等

     

    接下来的问题就是求多少组了:

    可以分为a b c 都相等  、 a b c 中有两个相等和abc都不想等这三种情况  

    下面我边写代码边解释:

    #include<iostream>

    #include<string.h>

    using namespace std;

     

    int main()

    {

        long long int n,a,b,c;///数据太大所以要用long long

     

        std::ios::sync_with_stdio(false);///加速cin cout  也可以直接使用c语言的输入输出

     

        while(cin>>n)

        {

            long long int ans = 0;///用来记录总种类数  ans=answer

            

            for(a = 1; a*a*a <= n; a++)///abc都相等的情况

                ans++;

     

            for(a = 1; a*a <= n; a++)///abc中有两个相同  相同的用a表示  另一个用b表示

            {

                b=n/a/a;///b并不是指的实际的b值 而是b的取值范围是1-b换句话说就是b的种类数

     

                if(b >= a)

                    ans += (b-1)*3;///因为ab一定是不相等的  所以 要从 1--b中减去 和a相等的那种情况

                    ///至于乘3  因为 aab的组合数  为 3      

     

                else

                    ans += b*3;///这种情况是  b的范围是  a之内  所以和a相等

            }

            

            ///地下是三者都不想等的情况  只要a1遍历到n  ba+1遍历到n  cb+1遍历到n   再乘以组合数6就可以了^_^

            for(a = 1; a*a <= n; a++)///abc都不相等的情况

            {

                for(b = a+1; a*b <= n; b++)

                {

                    c=n/a/b;

                    if(c>b)

                        ans+=(c-b)*6;///不用解释了吧

                    else

                        break;

                }

            }

     

            cout<<ans<<endl;

        }

        return 0;

    }

  • 相关阅读:
    'telnet' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
    Linux学习_009_VMware12.0 Pro 中安装 CentOS 6.8_超详解 + 高清大图
    Linux学习_008_Linux下的JDK和OpenJDK有什么具体的区别
    实战CentOS系统部署Hadoop集群服务
    开源多线程性能测试工具-sysbench
    Hadoop集群中Hbase的介绍、安装、使用
    Docker基础技术:Linux Namespace(上)
    带你走进rsync的世界
    5分钟教你Windows 10中将“运行”固定到开始菜单
    使用 Github Pages 发布你的项目文档
  • 原文地址:https://www.cnblogs.com/zhanzhao/p/3525267.html
Copyright © 2011-2022 走看看