zoukankan      html  css  js  c++  java
  • 【SSLOJ】HR的疑惑

    题目

    \([1,n]\) 中有多少个数能写作 \(a^b(b>1\)\(a,b\) 均为正整数 \()\)
    \(n\leq 10^{18}\)

    思路

    容易发现,只有当一个数字 \(k\) 被表示成 \(a^b\),且 \(a=a'^{b'}\) 时才会计算重复。所以考虑如何对任意一个数 \(k\) 只计算 \(b\) 最小的方案。
    为了防止 \(b\) 被拆分成 \(a'^{b'}\),只枚举 \([1,64]\) 中的质数作为指数即可。
    发现当 \(b=2\) 时,任意 \(a^b\) 都不会计算重复,所以直接将不超过 \(n^{\frac{1}{2}}\) 的数字记录贡献。
    对于 \(b>2\),发现最多有 \(n^{\frac{1}{3}}=10^6\) 个数字,所以考虑枚举底数,然后暴力判断得到的数字是否已经记录过贡献。
    用一个 \(\operatorname{STL::map}\) 记录每个数字是否计算过贡献即可。注意要特判指数为 2 的情况。
    时间复杂度 \(O(n^{\frac{1}{3}}\log n)\)\(\operatorname{STL::map}\) 的时间忽略不计 (bushi。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int LG=65,M=18;
    const int prm[20]={0,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61};
    ll n,ans;
    map<ll,bool> vis;
    
    int main()
    {
    	scanf("%lld",&n);
    	ans=pow(n,0.5);
    	for (register int i=1;i<=M;i++)
    	{
    		int Maxn=pow(n,1.0/prm[i]);
    		for (register int j=2;j<=Maxn;j++)
    		{
    			ll p=pow(j,0.5),q=pow(j,prm[i]);
    			if (p*p==j || vis[q]) continue;
    			vis[q]=1;
    			ans++;
    		}
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    Python统计nginx日志域名下载量
    如何使用MySQL自动化备份脚本添加备份任务
    迁移数据库报错
    cobbler
    Zabbix添加nginx-php监控
    Zookeeper运维问题集锦
    Jira+Wiki配置手册
    Gitlab安装恢复手册
    Glusterfs配置手册
    k8s的认证-RBAC机制
  • 原文地址:https://www.cnblogs.com/stoorz/p/13475058.html
Copyright © 2011-2022 走看看