HDU-2204- Eddy’s爱好 (容斥原理)

题意

给出一个数n,问1-n中有多少个数可以表示为m^k,m,k均为正整数且k>1

(1<=n<=1^18)

题解

(一开始^以为是异或懵逼了好久....)

额,显然1这个数比较讨厌1的多少次方都得1,对答案的贡献为1,最后加上就可以了。

然后,我们发现x^4=(x^2)^2四次方可以用平方的平方代替,我们只枚举质数次方,然后用n(1/x)等于x次方在n之内的数的个数(这个东西会有精度问题)。

就可以求出质数次方在1到n之内的数有多少。但是,发现(x^2)^3==(x^3)^2,(x^2)^3(或者说(x^3)^2)被算了两次。

这时,就用到容斥原理了。因为2^60>1e18所以质数次方考虑到59,又因为2*3*5*7=210>60,所以容斥时容斥到三个数就行了。

(容斥原理居然是小学奥数4大定理之一)

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 long long prime[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59};
 8 long long n,ans;
 9 void dfs(long long now,long long num,long long res,long long k){
10     if(res==0){
11         long long tmp=pow(n,1.0/num);
12         if(pow(tmp,(double)num)>n) tmp--;
13         tmp--;
14         if(tmp>0){
15             if(k&1)ans+=tmp;
16             else ans-=tmp;
17         }
18         return;
19     }
20     if(now>17)return;
21     if(num*prime[now]<60)dfs(now+1,num*prime[now],res-1,k);
22     dfs(now+1,num,res,k);
23 }
24 int main(){
25     while(scanf("%lld",&n)!=EOF){
26         ans=0;
27         for(long long i=1;i<=3;i++)dfs(1,1,i,i);
28         printf("%lld\n",ans+1);
29     }
30     return 0;
31 } 

 

转载于:https://www.cnblogs.com/Xu-daxia/p/9710032.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值