题意:给你一个正整数N,确定在1到N之间有多少个可以表示成M^K(K>1)的数。
我们可以由n^(1/p),知道指数为p的有多少个数。
通过观察,可以发现若一个数可以表示成x^(k*t),则可以表示成(x^k)^t。因此指数必然为素数。
枚举素数便可以得到指数为p的个数,但是可能出现重复,例如:x^3=y^5,其中x=t^5,y=t^3。
运用容斥原理,设a[i]表示指数为第i个素数的个数,那么答案等于满足一个的,减去两个的,加上三个的……
由于2^60>10^18,2*3*5*7>60,所以只要枚举到三即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<vector> 5 #define EPS 1e-8 6 #define MAXN 65 7 typedef long long LL; 8 using namespace std; 9 bool p[MAXN]; 10 vector<int> prime; 11 void Init() { 12 int i, j; 13 memset(p, true, sizeof(p)); 14 for (i = 2; i < 9; i++) { 15 if (p[i]) { 16 for (j = i * i; j < MAXN; j += i) 17 p[j] = false; 18 } 19 } 20 prime.clear(); 21 for (i = 2; i < MAXN; i++) { 22 if (p[i]) 23 prime.push_back(i); 24 } 25 } 26 int main() { 27 LL n, tmp; 28 int i, j, k, ans; 29 Init(); 30 while (~scanf("%I64d", &n)) { 31 ans = 1; 32 for (i = 0; i < (int) prime.size(); i++) { 33 tmp = (LL) (pow((double) n, 1.0 / prime[i]) + EPS); 34 if (tmp == 1) 35 break; 36 ans += tmp - 1; 37 } 38 for (i = 0; i < (int) prime.size(); i++) { 39 for (j = i + 1; j < (int) prime.size(); j++) { 40 tmp = (LL) (pow((double) n, 1.0 / (prime[i] * prime[j])) + EPS); 41 if (tmp == 1) 42 break; 43 ans -= tmp - 1; 44 } 45 } 46 for (i = 0; i < (int) prime.size(); i++) { 47 for (j = i + 1; j < (int) prime.size(); j++) { 48 for (k = j + 1; k < (int) prime.size(); k++) { 49 tmp = (LL) (pow((double) n, 50 1.0 / (prime[i] * prime[j] * prime[k])) + EPS); 51 if (tmp == 1) 52 break; 53 ans += tmp - 1; 54 } 55 } 56 } 57 printf("%d\n", ans); 58 } 59 return 0; 60 }