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 }