zoukankan      html  css  js  c++  java
  • 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
    ",ans+1);
    29     }
    30     return 0;
    31 } 
  • 相关阅读:
    WCF里几个基本知识点
    MVC3+EntityFramework实践笔记
    一些vim的插件和配置
    Web API工作方式
    计算机中的异常
    Glusterfs之nfs模块源码分析
    ASP.NET Windows身份认证
    Sql Server表结构及索引辅助查看工具
    sql server批量插入与更新两种解决方案
    如何在ViewModel中正确地使用Timer(定时器)
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9710032.html
Copyright © 2011-2022 走看看