UVa1655 Solution

Rikka is a high school girl suffering seriously from Ch¯uniby¯o (the age of fourteen would either act like
a know-it-all adult, or thinks they have special powers no one else has. You might google it for detailed
explanation) who, unfortunately, performs badly at math courses. After scoring so poorly on her maths
test, she is faced with the situation that her club would be disband if her scores keeps low.
Believe it or not, in the next exam she faces a hard problem described as follows.
Let’s denote f(x) number of ordered pairs satisfying (a ∗ b)|x (that is, x mod (a ∗ b) = 0)
where a and b are positive integers. Given a positive integer n, Rikka is required to solve
for f(1) + f(2) + … + f(n).
According to story development we know that Rikka scores slightly higher than average, meaning
she must have solved this problem.
So, how does she manage to do so?
Input
There are several test cases.
For each test case, there is a single line containing only one integer n (1 ≤ n ≤ 1011).
Input is terminated by EOF.
Output
For each test case, output one line ‘Case X: Y ’ where X is the test case number (starting from 1)
and Y is the desired answer.
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

题意:
定义f(x)为满足ab|x的(a,b)个数。输入n,输出 n1 ∑ 1 n f(i)的值。多组数据。

My题解:

先研究单个f(x)
ab|x等价于存在c使得abc=x,所以求满足ab|x的(a,b)组数等价于求满足abc=x的(a,b,c)组数。(因为x确定之后每一个(a,b)对应且仅对应一个(a,b,c)即(a,b,x/a/b))
再考虑 n1 ∑ 1 n f(i)
由上面所述的单个f(x)求法,可以发现,求 n1 ∑ 1 n f(i)实则等价于求abk<=n的三元组(a,b,c)的个数。题目的思路大体有了。
实现方法
因为三元组是有序的,所以不妨只计算满足a<=b<=c的三元组(a,b,c)的个数,然后乘以其对应的全排列数得到答案。下面将这样的三元组简称单增组。
单增组(a,b,c)的可能情况如下:

  1. a,b,c互不相等即ABC型
  2. a,b,c有且仅有两个数相等即AAB型(显然相等的两个数任何一个都小于第三个数)
  3. a,b,c三个数相等即AAA型

对于情况1,计算后乘A(3,2)=6;
对于情况2,计算后乘A(3,2)/A(2,1)=3;
对于情况3,计算后乘A(3,2)/A(3,2)=1.

枚举a和b,计算c的合法值个数。c的合法值个数就是单增组个数。
枚举计算时充分利用不等关系:a<=n1.0/2,b<=n1.0/3。不等关系比较显然,利用了之前定义了的单增组的特性。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL SqRt(LL Bas)
{
    LL ret = sqrt(Bas);
    while((ret+1ll)*(ret+1ll) <= Bas)
        ret++;
    return ret;
}
LL CuRt(LL Bas)
{
    LL ret = pow(Bas, 1.0/3);
    while((ret+1ll)*(ret+1ll)*(ret+1ll) <= Bas)
        ret++;
    return ret;
}
LL ABC(LL n)
{
    const LL lim_i = CuRt(n), lim_j = SqRt(n);
    LL k, ret = 0;
    for(LL i=1; i<=lim_i; i++)
    {
        for(LL j=i+1; j<=lim_j; j++)
        {
            k = n / i / j - j;
            if(k <= 0)
                break;
            ret += k;
        }
    }
    return ret*6ll;
}
LL AAB(LL n)
{
    const LL lim_ij = SqRt(n), MaxRep = CuRt(n);
    LL k, ret = 0;
    for(LL ij=1; ij<=lim_ij; ij++)
    {
        k = n / ij / ij;
        if(k <= 0)
            break;
        if(ij <= MaxRep)
            ret += k - 1ll;
        else
            ret += k;
    }
    return ret * 3ll;
}
LL AAA(LL n)
{
    return CuRt(n);
}
int main()
{
    LL n, rt2, rt3, res=0;
    int cnt=0;
    while(cin>>n)
    {
        res = ABC(n) + AAB(n) + AAA(n);
        cout<<"Case "<<++cnt<<": "<<res<<endl;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值