数学(hdu3208 - Integer’s Power)

F.A.Q
Hand In Hand
Online Acmers
Forum | Discuss
Statistical Charts
Problem Archive
Realtime Judge Status
Authors Ranklist
 
      C/C++/Java Exams     
ACM Steps
Go to Job
Contest LiveCast
ICPC@China
Best Coder beta
VIP | STD Contests
Virtual Contests 
    DIY | Web-DIY beta
Recent Contests
 

Integer’s Power

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1550    Accepted Submission(s): 284


Problem Description
LMY and YY are number theory lovers. They like to find and solve some interesting number theory problems together. One day, they become interested in some special numbers, which can be expressed as powers of smaller numbers.

For example, 9=3^2, 64=2^6, 1000=10^3 …

For a given positive integer y, if we can find a largest integer k and a smallest positive integer x, such that x^k=y, then the power of y is regarded as k.
It is very easy to find the power of an integer. For example:

The power of 9 is 2.
The power of 64 is 6.
The power of 1000 is 3.
The power of 99 is 1.
The power of 1 does not exist.

But YY wants to calculate the sum of the power of the integers from a to b. It seems not easy. Can you help him?
 

Input
The input consists of multiple test cases.
For each test case, there is one line containing two integers a and b. (2<=a<=b<=10^18)

End of input is indicated by a line containing two zeros.
 

Output
For each test case, output the sum of the power of the integers from a to b.
 

Sample Input
      
      
2 10 248832 248832 0 0
 

Sample Output
      
      
13 5

参考 思路

可以利用前缀和的思想,算出第一个数总共有的和,然后减去第二个数总共的和。怎么算和呢?因为pow(n, 1.0 / k),得出的数是n之内有几个数能开k次方。那么我们可以对n开1次方、2次……直到开出的数<2但是这里面有不合法的。比如22∗343,显然64的值是6,能开3次方的数中4是无效的。如何除去这种数?算出每个被开方数i的倍数,如果该数有效(< 60),dp[i] -= dp[j]。

然后我们分别计算(r-1)^k,r^k,(r+1)^k,然后看这三个数哪个最接近n就行了,这里要注意(r+1)^k计算时可能会超过LL,所以有一些处理。然后就是相当于容斥的部分了。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=110;
const LL INF=1e18+300;
const LL T=(1LL<<31);
LL num[maxn];
LL pow_mul(LL x,LL k)
{
    LL ans=1;
    while(k)
    {
        if(k&1)
        {
            double judge=1.0*INF/ans;
            if(x>judge)return -1;
            ans*=x;
        }
        k>>=1;
        if(x>T&&k>0)return -1;
        x*=x;
    }
    return ans;
}

LL find(LL x,LL k)
{
    LL r=(LL)pow(x,1.0/k);
    LL p=pow_mul(r,k);
    if(p==x)return r;
    if(p>x||p==-1)r--;
    else 
    {
        LL tmp=pow_mul(r+1,k);
        if(tmp!=-1&&tmp<=x)r++;
    }
    return r;
}
LL cal(LL n)
{
    int i;
    memset(num,0,sizeof(num));
    if(n<=3)return n;
    num[1]=n;
    for(i=2;i<63;i++)
    {
        num[i]=find(n,i)-1;
        if(!num[i])break;
    }
    int k=i;
    for(int j=k-1;j>0;j--)
        for(i=1;i<j;i++)
            if(j%i==0)num[i]-=num[j];
    LL ans=num[1];
    for(int i=2;i<k;i++)
        ans+=(i*num[i]);
    return ans;
}
int main()
{
    LL N,M;
    while(scanf("%lld%lld",&N,&M)!=EOF)
    {
        if(N==0&&M==0)break;
        printf("%lld\n",cal(M)-cal(N-1));
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值