hdu 2204 Eddy's爱好

求$[1,n]$种有多少正整数可以表示为$p^q$的形式,其中$p,q$为正整数,且$q \ge 2$

$1 \le n \le 10^{18}$

1. 若$p^q \le n$,则$\forall t \le p$,有$t^q \le n$

2. $p^q \le n \Rightarrow p \le \lfloor \sqrt[q]n \rfloor$,即$[1,n]$中可以写成$p^q$的$p$的个数为$\lfloor \sqrt[q]n \rfloor$

3. $p^q=(p^{a})^{b}=(p^{b})^{a}$,其中$a$为素数

枚举素数$a$,考虑所有$p^a$形式的数如何统计入答案

对于一个数$x=p^q$,设$p$不含非$1$的平方因子,$q$有$t$个质因子

这是一个经典容斥问题,即找一个函数$f(i)$,使得$\sum\limits_{i=1}^{t}{t \choose i}f(i)=1$成立

显然$f(i)=(-1)^{i+1}$

枚举指数是由哪些素数构成的,然后乘上容斥系数即可

由于$10^{2 \times 3 \times 5 \times 7} \gt 10^{18}$,因此只需要最多枚举三个素数即可

由于$2^{60} \gt 10^{18}$,因此素数只需要枚举到$59$即可(大概有$17$个)

状态量大约为${17 \choose 1} + {17 \choose 2} + {17 \choose 3}=17+136+680=833$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 
 5 ll n;
 6 const int N = 100;
 7 int vis[N], p[N], tot;
 8 
 9 ll calc(ll x) {
10     return (long long) pow(n, 1.0 / x) - 1;
11 }
12 
13 void sol() {
14     ll ans = 1;
15     for(int i = 1 ; i <= tot && calc(p[i]) ; ++ i) {
16         ans += calc(p[i]);
17         for(int j = i + 1 ; j <= tot && calc(p[i] * p[j]) ; ++ j) {
18             ans -= calc(p[i] * p[j]);
19             for(int k = j + 1 ; k <= tot && calc(p[i] * p[j] * p[k]) ; ++ k) {
20                 ans += calc(p[i] * p[j] * p[k]);
21             }
22         }
23     }
24     cout << ans << endl;
25 }
26 
27 int main() {
28     for(int i = 2 ; i < N ; ++ i) {
29         if(!vis[i]) p[++ tot] = i;
30         for(int j = 1 ; j <= tot && i * p[j] < N ; ++ j) {
31             vis[i * p[j]] = 1;
32             if(i % p[j] == 0) break;
33         }
34     }
35     while(cin >> n) sol();
36 }
hdu 2204 Eddy's爱好

转载于:https://www.cnblogs.com/KingSann/articles/9554488.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值