zoukankan      html  css  js  c++  java
  • HDU 4473 HDOJ Exam 2012ACM亚洲赛成都赛区J题

    http://acm.hdu.edu.cn/showproblem.php?pid=4473

      比赛的时候,这道题我由于思路始终不能从对n开平方深入到正解的对n开三次方,很遗憾没有出。赛后听了题解,恍然大悟。

      以为自己平时思路挺灵活的,现在想想比赛的时候思路还真是僵化啊。

    题目意思:

      定义f(x) = 满足(a * b)|x的有序对(a,b)的个数。

      然后输入一个n,求f(1) + f(2) + ... + f(n)

    废话不多说,此题的关键在于:

      把原题的条件(a * b)|x 转化为 a * b * y = x

      然后就很好计算了,就是,输入一个n,计算有多少有序对(a, b ,y)满足a*b*y<=n

      不妨设a<=b<=y

      则,a<=n^(1/3) , b<=sqrt(n/a)

      那么

        对于三个数字都相同的情况,只计算一次: i i i

        对于三个数字中有两个相同的情况,计算3次: i i j, i j i, j i i

        对于均不相同的情况,计算6次: a b y ,a y b ,b a y ,b y a, y a b ,y b a

    程序如下:注意在HDOJ上使用%I64d,但是现场赛使用%lld

     1 #include<cmath>
     2 #include<cstdio>
     3 using namespace std;
     4 typedef long long ll;
     5 ll pow2(ll n){//高精度开平方
     6     ll m=pow(n,0.5);
     7     while(m*m<=n) m++;
     8     while(m*m>n) m--;
     9     return m;
    10 }
    11 ll pow3(ll n){//高精度开立方
    12     ll m=pow(n,1.0/3);
    13     while(m*m*m<=n) m++;
    14     while(m*m*m>n) m--;
    15     return m;
    16 }
    17 int main()
    18 {
    19     int C=0;
    20     ll n;
    21     while (~scanf("%I64d",&n)){
    22         ll m=pow3(n),ans=m;//第一种情况m个
    23         for(int i=1;i<=m;i++){
    24             ll ni=n/i,k=pow2(ni);//n/i下面多次用到,只计算一次,常数优化
    25             ans+=(ni/i + k - i*2)*3;//计算第二种情况,其中i i j有(ni/i - i)个,i j j有(k - i)个
    26             for(int j=i+1;j<=k;j++)
    27                 ans+=(ni/j - j)*6;//计算第三种情况
    28         }
    29         printf("Case %d: %I64d\n",++C,ans);
    30     }
    31     return 0;
    32 }
  • 相关阅读:
    linux命令练习
    Centos修改用户密码
    Git使用
    使用SecureCRT连接虚拟机中Linux系统 和 虚拟机网络配置
    CentOS里Tomcat端口开放
    Linux下安装Tomcat
    laravel 中将DB::select 得到的内容转为数组
    nginx 转发 由于php语法错误 导致的 50x
    windows 下后台启动 redis
    sublime 非常好用的注释工具
  • 原文地址:https://www.cnblogs.com/hundundm/p/2775191.html
Copyright © 2011-2022 走看看