hdu 3208 Integer’s Power(容斥原理)

看着和hdu 2204有些相似,但是解法还是有差距的。求(a,b)之间的数字的幂的和,求出来1-b的减去1-(a-1)的即可。一个数字表示成M^K,取那个最大的K作为这个数字的幂。考虑枚举所有的幂,2^60>1e18,所以从2枚举到59就行。比如64可以表示成2^6,4^3,8^2,则64的幂就是6。但是有重复,就用到容斥了,8^2已经包含64了,但是64的幂是6,所以就要去掉8^2这种情况,也要去掉4^3的情况。还会发现6%3=0,6%2=0。
参考:http://blog.csdn.net/u010660276/article/details/45460973
学会了写开高次方的函数,涨知识了。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const LL INF = 1e18+300;
const int MAXN = 110;
const LL T = (1LL<<31);


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 num[MAXN];

LL solve(LL n)
{
    memset(num,0,sizeof(num));
    int numLen = 0,i;
    num[1] = n;
    for(i = 2; i < 60; ++i)
    {
        num[i] = find(n,i)-1;
        if(num[i] == 0)
            break;
    }
    numLen = i;
    for(int j = numLen-1; j > 0; --j)
        for(int k = 1; k < j; ++k)
            if(j%k == 0)
                num[k] -= num[j];
    LL res = 0;
    for(int i = 1; i < numLen; ++i)
        res += num[i]*i;
    return res;
}


int main()
{
    LL a,b;
    while(cin >> a >> b && a+b)
        cout << solve(b)-solve(a-1) <<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值