题意:给定一个区间,求不能表示成k*x*x*x(x>1)的个数。
区间转化为两个1~n,可以先求出能够表示成k*x*x*x(x>1)的个数。
不妨假设x是某个素数,1~n中有n/(x^3)个值,x^3,2*x^3,……,n/(x^3)*x^3。
假设t不是素数,可以表示t=k*x。那么t^3=(k*x)^3=k^3*x^3。显然会与x统计重复。
所以,可以枚举素数的三次方,得到一个答案。
但是,6^3=(2^3)*(3^3),被计算了两次。因此,需要用到容斥原理。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #define MAXN 2650000 5 typedef long long LL; 6 using namespace std; 7 vector<LL> cub; 8 bool p[MAXN]; 9 LL tmp, limit; 10 int depth; 11 void Init() { 12 int i, j; 13 cub.clear(); 14 memset(p, true, sizeof(p)); 15 for (i = 2; i < 1630; i++) { 16 if (p[i]) { 17 for (j = i * i; j < MAXN; j += i) 18 p[j] = false; 19 } 20 } 21 for (i = 2; i < MAXN; i++) { 22 if (p[i]) 23 cub.push_back((LL) i * i * i); 24 } 25 } 26 void DFS(int index, int now, LL mul) { 27 if (now == depth) 28 tmp += limit / mul; 29 else { 30 int i; 31 for (i = index; cub[i] <= limit; i++) { 32 if (mul > limit / cub[i]) 33 break; 34 DFS(i + 1, now + 1, mul * cub[i]); 35 } 36 } 37 } 38 LL Count(LL n) { 39 LL ans = 0; 40 limit = n; 41 for (depth = 1;; depth++) { 42 tmp = 0; 43 DFS(0, 0, 1); 44 if (tmp) { 45 if (depth & 1) 46 ans += tmp; 47 else 48 ans -= tmp; 49 } else 50 break; 51 } 52 return n - ans; 53 } 54 int main() { 55 int c; 56 LL low, high; 57 Init(); 58 scanf("%d", &c); 59 while (c--) { 60 scanf("%lld%lld", &low, &high); 61 printf("%lld\n", Count(high - 1) - Count(low - 1)); 62 } 63 return 0; 64 }