hdu2204Eddy's爱好(数论+容斥原理)

 

 

Problem Description

Ignatius 喜欢收集蝴蝶标本和邮票,但是Eddy的爱好很特别,他对数字比较感兴趣,他曾经一度沉迷于素数,而现在他对于一些新的特殊数比较有兴趣。
这些特殊数是这样的:这些数都能表示成M^K,M和K是正整数且K>1。
正当他再度沉迷的时候,他发现不知道什么时候才能知道这样的数字的数量,因此他又求助于你这位聪明的程序员,请你帮他用程序解决这个问题。
为了简化,问题是这样的:给你一个正整数N,确定在1到N之间有多少个可以表示成M^K(K>1)的数。

 

 

Input

本题有多组测试数据,每组包含一个整数N,1<=N<=1000000000000000000(10^18).

 

 

Output

对于每组输入,请输出在在1到N之间形式如M^K的数的总数。
每组输出占一行。

 

 

Sample Input

 

10 36 1000000000000000000

 

 

Sample Output

 

4 9 10010033

 


 

As we konw ,1~n中能整开k次方的数有个,,也就是(int)pow(n,1.0/k)个,

而要求1~n中所有能够被整开的数有几个,那就是  pow(n,1.0/2)+ pow(n,1.0/3)+······

这样看来,有很多被重复计算了,比如能开4次方、6次方、8次方的一定能开2次方

所以,我们第一次计算开k次方的时候,就要去除所有能k的倍数次方的

而这就恰是素数的性质,由于数据在long long(2^63-1)的范围,所以只需算出前63个素数就行,

但是,万一素数与素数之间重复计算了怎么办,那就需要用到容斥原理了,加上奇数个减去偶数个

只需要统计三个素数相乘的幂就行了,因为四个会超出范围

#include<bits/stdc++.h>
#define lom long long 
using namespace std;
int p[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61};
int main()
{
    lom n;
    while(cin>>n)
    {
        lom ans=1,temp;
        for(int i=0;;i++)
        {
            temp=(lom)pow(n,1.0/p[i]);
            if(temp<2) break;
            ans+=temp-1;
            
            for(int j=i+1;;j++)
            {
                temp=(lom)pow(n,1.0/p[i]/p[j]);
                if(temp<2) break;
                ans-=temp-1;
                
                for(int k=j+1;;k++)
                {
                    temp=(lom)pow(n,1.0/p[i]/p[j]/p[k]);
                    if(temp<2) break;
                    ans+=temp-1;
                }
            }
        }
        cout<<ans<<endl;
    }
    return 0;
} 

/*
膜膜膜  膜 膜        膜       膜     膜                  

 膜 膜膜膜膜膜膜膜膜      膜        膜    膜                  

 膜 膜  膜 膜        膜      膜膜膜膜 膜膜膜膜膜膜               

 膜膜膜 膜膜膜膜膜       膜         膜 膜 膜  膜               

 膜 膜 膜   膜  膜膜膜膜膜膜膜膜膜膜膜   膜  膜 膜  膜               

 膜 膜 膜膜膜膜膜       膜        膜膜 膜膜膜膜膜膜               

 膜膜膜 膜   膜      膜 膜      膜膜 膜膜 膜  膜               

 膜 膜 膜膜膜膜膜      膜 膜     膜 膜  膜 膜  膜               

 膜 膜   膜       膜   膜      膜  膜膜膜膜膜膜               

 膜 膜膜膜膜膜膜膜膜    膜   膜      膜  膜 膜  膜               

 膜 膜  膜 膜     膜     膜     膜    膜                  

膜 膜膜 膜   膜膜 膜膜       膜膜   膜    膜          
*/ 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值