HDU 4473 Exam 2012成都现场赛J题(规律+思维)

来源:互联网 发布:网络摄像头密码重置 编辑:程序博客网 时间:2024/04/28 07:38

       题目大意:给你一个n,找出所有<=n,从1一直到n的f(x)和。

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

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


      解题思路:把原题的条件(a * b)|x 转化为 a * b * c = x这个才是关键。

         先规定a<=b<=c便于讨论。

         然后分类a=b=c个数×1  (a=b<c和a<b=c)×3   a<b<c个数×6,自己可以在纸上模拟序数的情况。这道题首先就是思维上必须有个突破,并不是以往那种简单的找规律。而是需要我们转换思路a*b  * c = x能想到这里,剩下的基本上都可以写出来了。思维跳跃性也不大,只是需要去发现。说这个题是思维题,还有一点,一般求S(n)都需要先求前n项,找递推关系,而这个题是直接Sn.


       题目地址:HDU 4473 Exam


#include <iostream>#include<cmath>#include<cstdio>using namespace std;long long cal2(long long x){     long long mid = floor(pow(x,0.5));     while(mid*mid<=x) mid++;     while(mid*mid>x) mid--;     return mid;}long long cal3(long long x){     long long mid = floor(pow(x,double(1.0/3.0)));     while(mid*mid*mid<=x) mid++;     while(mid*mid*mid>x) mid--;     return mid;}int main(){    long long n,res,t1,t2,i,j,res2,res3;    int cas=0;    while(~scanf("%I64d",&n))    {        printf("Case %d: ",++cas);        t1=cal3(n); res=t1;  //第一种情况(a=b=c)        t2=cal2(n);        res2=0; res3=0;        //a<b<c;        for(i=1;i<=t1;i++)        {          res2+=n/(i*i)-i;    //a=b<c;          res2+=cal2(n/i)-i;  //a<b=c;          for(j=i+1;j<=t2;j++)          {            if(n/(i*j)<=j)               break;            res3+=n/(i*j)-j;  //a<b<c;          }        }        res+=res2*3;    //第二种情况        res+=res3*6;    //第三种情况        printf("%I64d\n",res);    }    return 0;}