容斥原理:ans = 指数为一个质数 U 指数为两个质数 U 指数为3个指数。
如果为4个质数即2 * 3 * 5 * 7 > 60。那么这个数肯定超过了 n,所以最多只需要枚举到三个质数。
这里指数一定为不一样的质数,因为如果一样就变成了x * x = x ^ 2。
即y ^ (x * x) = y ^ x ^ 2 = (y ^ x) ^ 2。
那么他一定被包含在了指数为2的情况中。
从此可见,若指数不为质数 = t ^ (x * y)。那么这个数就可以表示为 (t ^ x) ^ y。
那么他就会被包含在了指数为y的方案中,所以我们只需要统计所有指数为质数的情况。
对于区间[1,n]。里面有多少指数为k的个数 = n ^ (1 / k)。
然后我们容斥即可。
有容斥原理可知ans = 指数为一个质数的 - 指数为两个质数的 + 指数为三个质数的。
#include<iostream> #include<stdio.h> #include<queue> #include<algorithm> #include<math.h> #include<stack> #include<map> #include<limits.h> #include<vector> #include<string.h> #include<string> using namespace std; typedef long long LL; typedef pair<LL,int> pii; const int N = 65; const int M = 1e5 + 5; const LL Mod = 199999; #define pi acos(-1) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } void print(int x){ if(x < 0){x = -x;putchar('-');} if(x > 9) print(x/10); putchar(x%10+'0'); } } using namespace FASTIO; bool vis[N]; int prime[N],tot = 0,ans[N]; void init() { for(int i = 2;i < N;++i) { if(!vis[i]) { prime[++tot] = i; } for(int j = 1;j <= tot && prime[j] * i < N;++j) { vis[prime[j] * i] = 1; if(i % prime[j] == 0) break; } } } int main() { init(); LL n; while(cin >> n) { memset(ans,0,sizeof(ans)); for(int i = 1;i <= tot;++i) { LL ma = pow(1.0 * n,1.0 / prime[i]); ans[1] += ma - 1; } for(int i = 1;i <= tot;++i) { for(int j = i + 1;j <= tot;++j) { LL ta = prime[i] * prime[j]; ans[2] += pow(1.0 * n,1.0 / ta) - 1; } } for(int i = 1;i <= tot;++i) { for(int j = i + 1;j <= tot;++j) { for(int k = j + 1;k <= tot;++k) { LL ta = prime[i] * prime[j] * prime[k]; ans[3] += pow(1.0 * n,1.0 / ta) - 1; } } } printf("%lld ",ans[1] - ans[2] + ans[3] + 1);//1也算 } system("pause"); return 0; }