hdu 1695

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1695

给出a b c d k 在 [a,b] [c,d]内各找一个数,使得gcd(x,y) == k,也就是说 gcd(x / k, y / k) == 1,所以就是在 [1,b / k] [1, d / k]中找互质的对数。容斥原理和欧拉函数的应用,首先在打印素数的同时求出每个数的欧拉函数值,对于[1,b]内的数直接用欧拉数组求互质的对数,对于[b + 1,d]的数用容斥原理求互质对数,首先求出不互质的对数,然后用总的减去不互质的对数。比如说某个数 n ,首先求出 n 的所有因子num, 假设单个因子个数为num1,任意两个因子个数相乘所得因子个数num2,任意三个因子相乘所得因子个数num3 ~~~numn, 那么与n 不互质的个数 tnum = num1 - num2 + num3 - num4 + ~~~~ (-1) ^ (n - 1) numn

View Code
 1 typedef __int64 ll;
 2 const int N = 100001;
 3 int prime[N], phi[N];
 4 int num,tnum;
 5 void is_prime()  //  求欧拉函数
 6 {
 7     int i,j;
 8     phi[0] = 0, phi[1] = 1;
 9     for(i = 2; i < N; i++)
10     {
11         if(!phi[i])
12         {
13             phi[i] = i - 1;
14             prime[num ++] = i;
15         }
16         for(j = 0; (j < num) && (i * prime[j]) < N; j++)
17         {
18             if(i % prime[j] == 0)
19             {
20                 phi[i * prime[j]] = phi[i] * prime[j];
21                 break;
22             }
23             phi[i * prime[j]] = phi[i] * (prime[j] - 1);
24         }
25     }
26 }
27 ll solve(int n,int r)  // 容斥定理求互质个数
28 {
29     vector<int>p;
30     for(int i = 2; i * i <= n; i++)
31     {
32         if(n % i == 0) p.push_back(i); 
33         while(n % i == 0) n /= i;
34     }
35     if(n > 1) p.push_back(n);
36     ll sum = 0;
37     for(int j = 1; j < (1 << p.size()); j ++)
38     {
39         ll mult = 1, bit = 0;
40         for(int i = 0; i < (int)p.size(); i++)
41         {
42             if(j & (1 << i))
43             {
44                 bit ++;
45                 mult *= p[i];
46             }
47         }
48         ll cur = r / mult;
49         if(bit % 2) sum += cur;
50         else sum -= cur;
51     }
52     return r - sum;
53 }
54 int main()
55 {
56     int a,b,c,d,k;
57     int i;
58     int t,cs = 0;
59     is_prime();
60     //freopen("data.txt","r",stdin);
61     scanf("%d",&t);
62     while(t--)
63     {
64         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
65         printf("Case %d: ",++cs);
66         if(k == 0)
67         {
68             printf("%d\n",0);
69             continue;
70         }
71         b /= k, d /= k;
72         if(b > d) swap(b,d);
73         ll ans = 0;
74         for(i = 1; i <= b; i++)
75         ans += phi[i];
76         for(i = b + 1; i <= d; i++)
77         {
78             ans += solve(i,b);
79         }
80         cout<<ans<<endl;
81         //printf("%I64d\n",ans);
82         //printf("%lld\n",ans);
83     }
84     return 0;
85 }
posted @ 2012-10-11 17:22  AC_Girl  阅读(166)  评论(0编辑  收藏  举报