zoukankan      html  css  js  c++  java
  • HDU

    题意:求(1 - N(1le N le 1e18))中,能表示成(M^k(M>0,k>1))的数的个数
    分析:正整数p可以表示成(p = m^k = m^{r*k'})的形式,其中k'为素数。枚举幂k,求出满足(p^kle N)的最大的(p),则对于当前的(k),任意小于(p)的正整数(p'),都有(p'^{k}<N),因此在(1-N)范围内有(N^{frac{1}{k}})个满足条件的数。
    因为(2^{60}>10^{18}),所以枚举到的k'最多不超过60,预处理出60以内的所有素数。
    (2*3*5=30,2*3*5*7=210>60),所以最多只考虑3个素幂次相乘的情况。
    但是如此枚举会出现重复的情况,例如((2^{3})^{2} = (2^{2})^{3} = 2^6)在枚举(k=2)(k=3)时重复了,根据容斥的思想,枚举到偶数个素幂次相乘时,减去该结果。
    *注意每次计算(N^{frac{1}{k}})时,减去1的情况,最后将结果加1,因为1在每种情况中都会出现,不必重复。

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int maxn = 1e5+5;
    const LL prime[20]  ={2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59};
    const int len = 17;
    const double eps  =1e-8;
    LL ans;
    LL N;
    
    void dfs(int pos,int num,int tot,LL k = 1)
    {
        if(k>60) return;
        if(num==tot){
            LL p = (LL)(pow(N,1.0/(0.0+k))+eps)-1;
            ans +=p;
            return;    
        }
        if(pos==len) return;
        dfs(pos+1,num,tot,k);
        dfs(pos+1,num+1,tot,k*prime[pos]);
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        while(scanf("%lld",&N)==1){
            LL res= 0;
            for(int i =1;i<=3;++i){
                ans=0;
                dfs(0,0,i);
                if(i&1) res+=ans;
                else res-=ans;
            }
            res+=1;
            printf("%lld
    ",res);
        }
        return 0;
    }
    
    
    为了更好的明天
  • 相关阅读:
    Exchange调整入站SMTP连接超时时间
    使用WSS和SOFS管理集群存储--Storage
    String构造方法和字符集编码转换
    系统类和数学操作类
    JavaSE——数据类型流、内存流、打印流
    JavaSE——装饰设计模式+简单加密解密工程
    JavaSE——装饰设计模式
    JavaSE——装饰流
    JavaSE —— IO
    JavaSE —— IO简介
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9560228.html
Copyright © 2011-2022 走看看