HUD 4473 Exam

题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=4473


题目意思
定义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



超时代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
using namespace std;

typedef __int64 LL;
const int N=400005;
const LL II=1000000007;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);

LL pow3(LL n)
{
    LL p=(LL)pow(n,1.0/3);
    while(p*p*p<=n) p++;
    while(p*p*p>n)  p--;
    return p;
}

LL pow2(LL n)
{
    LL p=(LL)pow(n,1.0/2);
    while(p*p<=n) p++;
    while(p*p>n)  p--;
    return p;
}

int main()
{
    LL n;
    int ca=0;
    while(~scanf("%I64d",&n))
    {
        LL m,t,ans=0,i,j,k;
        m=pow3(n);t=pow2(n);
        for(i=1;i<=m;i++)
        for(j=i;j<=t;j++)
        for(k=j;k<=n;k++)
        {
            if(i*j*k>n) continue;
            if(i==j&&j==k)
                ans++;
            else if(i<j&&j<k)
                ans+=6;
            else
                ans+=3;
        }
        printf("Case %d: %I64d
",++ca,ans);
    }
    return 0;
}



AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
using namespace std;

typedef __int64 LL;
const int N=400005;
const LL II=1000000007;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);

LL pow3(LL n)
{
    LL p=(LL)pow(n,1.0/3);
    while(p*p*p<=n) p++;
    while(p*p*p>n)  p--;
    return p;
}

LL pow2(LL n)
{
    LL p=(LL)pow(n,1.0/2);
    while(p*p<=n) p++;
    while(p*p>n)  p--;
    return p;
}

int main()
{
    LL n;
    int ca=0;
    while(~scanf("%I64d",&n))
    {
        LL m,ans=0,i,j;
        m=pow3(n);
        ans+=m;//第一种,三个相等的情况
        for(i=1;i<=m;i++)
        {
            LL t=n/i;
            LL k=pow2(t);
            ans+=(t/i+k-i*2)*3;//第二种,前两个相等-后面的比前面的大,或则后两个相同比前面的大
            for(j=i+1;j<=k;j++)
                ans+=(t/j-j)*6;//第三种,都不相等从小到大
        }
        printf("Case %d: %I64d
",++ca,ans);
    }
    return 0;
}


原文地址:https://www.cnblogs.com/javawebsoa/p/3206394.html