Uestc 1720 【容斥原理】.cpp

题意:

  求1~n以内的无平方因子数的个数。

 

思路:

  利用类似筛选法把100010的素数标记出来(预处理)

  然后通过容斥原理,把有平方因子数的个数算出来,那总个数-有平方因子个数 = 答案了

  n之内有平方因子的数的个数sum  = n/(2^2) + n/(3^2)+……+n/(k^2) - n/(2^2 * 3^2)-……+……。

 

Tips:

  所谓容斥原理,其实举一个简单的例子就是:一个班里a个同学喜欢吃苹果,b个同学喜欢吃香蕉。问这个班有多少个同学。

  如果自己算的话就是a + b - a∩b

  这题也一样,把含2的k次方的个数算出来,含3的k次方的个数算出来,含5的k次方的个数算出来,含pri[i]的k次方的个数算出来........然后减去既含2的k次方也含3的k次方的个数,既含3的k次方也含5的k次方....既含pri[i]的k次方也含pri[i+1]的k次方....加上既含2的k次方也含3的k次方也含5的k次方..既含pri[i]的k次方也含pri[i+1]的k次方也含pri[i+2]的k次方的个数...

  容斥原理即包含个数为偶数的前面的符号为加,个数为奇数的前面的符号为减..

  主要是递归来解决容斥原理那里有点难理解,但是其实就是递归的时候把这一层的运算结果当做下一层的输入,这样就可以完成加加减减的操作了..

 

Code:

View Code
 1 #include <stdio.h>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <ctime>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 int pri[1000010];
 9 bool vis[1000010];
10 long long n;
11 int c;
12 
13 long long dfs(int d, long long t) {
14     long long sum = 0;
15     while(d < c && (long long)pri[d]*pri[d] <= n/t) {
16         sum += n/(t*pri[d]*pri[d]) - dfs(d+1, t*pri[d]*pri[d]);
17         d++;
18     }
19     return sum;
20 }
21 
22 int main()
23 {
24     int T;
25     long long ans;
26     c = 0;
27     memset(vis, 0, sizeof(vis));
28     for(int i = 2; i < 1000010; ++i)
29         if(!vis[i]) {
30             pri[c++] = i;
31             for(int j = i*2; j < 1000010; j += i) vis[j] = true;
32         }
33 
34     while(EOF != scanf("%d", &T))
35     while(T--) {
36         scanf("%lld", &n);
37         ans = dfs(0, 1);
38         printf("%lld\n", n-ans);
39     }
40     return 0;
41 }

 

链接:http://acm.uestc.edu.cn/problem.php?pid=1720

posted @ 2013-03-17 09:46  Griselda.  阅读(275)  评论(0编辑  收藏  举报