题意:给定一个区间,求不能表示成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 }
posted on 2012-09-07 09:11  DrunBee  阅读(300)  评论(0编辑  收藏  举报