HDU 2204 Eddy's爱好(容斥原理dfs写法)题解
2024-09-23 13:01:29
题意:定义如果一个数能表示为M^k,那么这个数是好数,问你1~n有几个好数。
思路:如果k是合数,显然会有重复,比如a^(b*c) == (a^b)^c,那么我们打个素数表,指数只枚举素数,2^60 > 1e18,所以打60以内素数就够了。但是显然指数为素数依然会有重复的,比如(a^b)^c == (a^c)^b,这里就要用到容斥了。我们如果用一个数组a[i]表示指数为第i个素数的数的个数,那么最终答案应该是,加上一个的,减去两个的,加上三个的(因为2 * 3 * 5 * 7 > 60,最多只能有三个相乘形成指数)。如果我要算出指数为p的这样的数有几个,那么可以计算pow(n,1.0/p)。先写了一个朴素版的,纯枚举;后来又写了一个dfs的,这样大于3也能用了。
讲一些小细节,每次算出个数我们都减去1这里是去掉了1^p,我们在最后答案加上1。最后一个样例答案是“1001003332”,我的“1001003331”但是过了。
容斥:对于几个集合求解并集大小,那么采用一种方法:加上所有单个集合,减去所有两个集合相并部分,加上所有三个集合相并部分,减去所有四个集合相并部分.....
参考:学习容斥原理
代码:
/*朴素写法1*/
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = + ;
const int seed = ;
const int MOD = + ;
const int INF = 0x3f3f3f3f;
int prime[], p[], pn;
ll ans, n;
void get(){
memset(p, , sizeof(p));
pn = ;
for(int i = ; i <= ; i++){
if(!p[i]){
prime[pn++] = i;
for(int j = i * i; j <= ; j += i){
p[j] = ;
}
}
}
}
int main(){
get();
while(~scanf("%lld", &n)){
ans = ;
ll ret;
for(int i = ; i < pn; i++){
ret = pow((double)n, 1.0 / prime[i]);
if(ret == ) break;
ans += ret - ;
}
for(int i = ; i < pn; i++){
for(int j = i + ; j < pn; j++){
ret = pow((double)n, 1.0 / (prime[i] * prime[j]));
if(ret == ) break;
ans -= ret - ;
}
}
for(int i = ; i < pn; i++){
for(int j = i + ; j < pn; j++){
for(int k = j + ; k < pn; k++){
ret = pow((double)n, 1.0 / (prime[i] * prime[j] * prime[k]));
if(ret == ) break;
ans += ret - ;
}
}
}
printf("%lld\n", ans + );
}
return ;
}
/*dfs写法*/
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = + ;
const int seed = ;
const int MOD = + ;
const int INF = 0x3f3f3f3f;
int prime[], p[], pn;
ll ans, n, flag;
void get(){
memset(p, , sizeof(p));
pn = ;
for(int i = ; i <= ; i++){
if(!p[i]){
prime[pn++] = i;
for(int j = i * i; j <= ; j += i){
p[j] = ;
}
}
}
}
void dfs(int start, int p, int times){
if(times == ){
ll ret = pow((double)n, 1.0 / p);
if(ret == ) return;
ret--;
ans += flag * ret;
return;
}
for(int i = start; i < pn; i++){
dfs(i + , p * prime[i], times - );
}
}
int main(){
get();
while(~scanf("%lld", &n)){
ans = ;
ll ret;
flag = -;
for(int i = ; i <= ; i++){
flag *= -;
dfs(, , i);
}
printf("%lld\n", ans + );
}
return ;
}
最新文章
- jQuey知识点三 解析json数据
- Ext JS 4 老特征:statics 静态的变量和方法
- Python之什么是函数
- js 获取iframe中的元素
- IIS mime类型
- I.MX6 Android 5.1 快速合成系统
- android中ImageView讲解
- iOS平常注意1
- 宏基5750G 不能用内置无线网卡上网
- HDU 3311 Dig The Wells(斯坦纳树)
- 【WebForm】Repeater 序列号 在翻页情况下自增
- Java面试题精选(一)基础概念和面向对象
- tomcatserver乱码问题,tomcat与数据库之间的编码统一转换
- SQL注入(一) - 入门篇
- SK-Learn 全家福
- 【java设计模式】【创建模式Creational Pattern】建造模式Builder Pattern
- java----SVN
- PBRT笔记(12)——蒙特卡洛积分
- Google SwipeRefreshLayout(Goolge官方下拉刷新控件)尝鲜
- Python DB operation
热门文章
- 正则验证ip
- 借用HTML5 插入视频。音频
- adb server version (31) doesn&#39;t match this client (36)
- Hardwood Species(stl map)
- 摘自(http://www.ruanyifeng.com/blog/2011/07/linux_load_average_explained.html)
- Django初级手册2-管理界面的使用及定制
- ng-深度学习-课程笔记-0: 概述
- Openstack创建虚拟机 Restful api和RPC调用
- mysql错误日志与通用日志
- python selenium第一个WebDriver脚本