UVa 10214 (莫比乌斯反演 or 欧拉函数) Trees in a Wood.

题意:

这道题和POJ 3090很相似,求|x|≤a,|y|≤b 中站在原点可见的整点的个数K,所有的整点个数为N(除去原点),求K/N

分析:

坐标轴上有四个可见的点,因为每个象限可见的点数都是一样的,所以我们只要求出第一象限可见的点数然后×4+4,即是K。

可见的点满足gcd(x, y) = 1,于是将问题转化为x∈[1, a], y∈[1, b],求gcd(x, y) = 1的个数。

类比HDU 1695可以用莫比乌斯反演来做,我还写了普通的和分块加速的两份代码,交上去发现运行时间相差并不是太多。

 1 #include <cstdio>
 2 #include <algorithm>
 3 typedef long long LL;
 4
 5 const int maxn = 2000;
 6 int mu[maxn+10], vis[maxn+10], prime[maxn];
 7
 8 void Mobius()
 9 {
10     mu[1] = 1;
11     int cnt = 0;
12     for(int i = 2; i <= maxn; ++i)
13     {
14         if(!vis[i])
15         {
16             mu[i] = -1;
17             prime[cnt++] = i;
18         }
19         for(int j = 0; j < cnt && (LL)i*prime[j] <= maxn; ++j)
20         {
21             vis[i*prime[j]] = 1;
22             if(i % prime[j] != 0) mu[i*prime[j]] = -mu[i];
23             else
24             {
25                 mu[i*prime[j]] = 0;
26                 break;
27             }
28         }
29     }
30     //计算前缀和,用于分块加速
31     for(int i = 2; i <= 2015; ++i) mu[i] += mu[i-1];
32
33 }
34
35 int main()
36 {
37     Mobius();
38     int a, b;
39     while(scanf("%d%d", &a, &b) == 2)
40     {
41         if(a == 0 && b == 0) break;
42         LL K = 0, N = (LL)(a*2+1) * (b*2+1) - 1;
43         if(a > b) std::swap(a, b);
44         for(int i = 1, j; i <= a; i = j + 1)
45         {
46             j = std::min(a/(a/i), b/(b/i));
47             K += (LL)(mu[j] - mu[i-1]) * (a/i) * (b/i);
48         }
49         //for(int i = 1; i <= a; ++i) K += (LL) mu[i] * (a/i) * (b/i);
50         K = (K+1)*4;
51
52         printf("%.7f\n", (double) K / N);
53     }
54
55     return 0;
56 }

代码君

也可以按照紫书上的思路求欧拉函数,因为a的范围比较小,所以可以逐列统计。不过这个方法要比上面的莫比乌斯反演慢得多

 1 #include <cstdio>
 2 #include <cmath>
 3 typedef long long LL;
 4
 5 int phi(int n)
 6 {
 7     int m = sqrt(n + 0.5);
 8     int ans = n;
 9     for(int i = 2; i <= m; ++i) if(n % i == 0)
10     {
11         ans = ans / i * (i-1);
12         while(n % i == 0) n /= i;
13     }
14     if(n > 1) ans = ans / n * (n-1);
15     return ans;
16 }
17
18 int gcd(int a, int b)
19 {
20     return b == 0 ? a : gcd(b, a%b);
21 }
22
23 int main()
24 {
25     int a, b;
26     while(scanf("%d%d", &a, &b) == 2 && a)
27     {
28         LL N = (LL)(a*2+1) * (b*2+1) - 1;
29         LL K = 0;
30         for(int x = 1; x <= a; ++x)
31         {
32             int k = b / x;
33             K += phi(x) * k;
34             for(int y = k*x+1; y <= b; y++)
35                 if(gcd(x, y) == 1) K++;
36         }
37         K = (K+1)*4;
38         printf("%.7f\n", (double)K / N);
39     }
40
41     return 0;
42 }

代码君二

时间: 2024-08-08 01:16:28

UVa 10214 (莫比乌斯反演 or 欧拉函数) Trees in a Wood.的相关文章

BZOJ 2818 Gcd (莫比乌斯反演 或 欧拉函数)

2818: Gcd Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 2534  Solved: 1129 [Submit][Status][Discuss] Description 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的 数对(x,y)有多少对. Input 一个整数N Output 如题 Sample Input 4 Sample Output 4 HINT hint 对于样例(2,2),(2,4),(3,3),(4,2)

【BZOJ2226】[Spoj 5971] LCMSum 莫比乌斯反演(欧拉函数?)

[BZOJ2226][Spoj 5971] LCMSum Description Given n, calculate the sum LCM(1,n) + LCM(2,n) + .. + LCM(n,n), where LCM(i,n) denotes the Least Common Multiple of the integers i and n. Input The first line contains T the number of test cases. Each of the n

UVA 10837 - A Research Problem(欧拉函数)

UVA 10837 - A Research Problem 题目链接 题意:给定phi(n),求最小满足的最小的n 思路:phi(n)=pk11(p1?1)?pk22(p2?1)?pk33(p3?1)....(p为质数),因此对于给定phi(n),先把满足条件phi(n)%(p?1)=0的素数全找出来,在这些素数基础上进行暴力搜索,枚举哪些素数用与不用,求出最小值.这样做看似时间复杂度很高,但是实际上,由于每次多选一个素数之后对于值是呈指数上升的,所以实际组合出来的情况并不会太多,因此是可行的

uva 10837 - A Research Problem(欧拉函数+暴力)

题目链接:uva 10837 - A Research Problem 题目大意:给定一个phin,要求一个最小的n,欧拉函数n等于phin 解题思路:欧拉函数性质有,p为素数的话有phip=p?1;如果p和q互质的话有phip?q=phip?phiq 然后根据这样的性质,n=pk11(p1?1)?pk22(p2?1)???pkii(pi?1),将所有的pi处理出来,暴力搜索维护最小值,虽然看上去复杂度非常高,但是因为对于垒乘来说,增长非常快,所以搜索范围大大被缩小了. #include <cs

UVA 11426 - GCD - Extreme (II) 欧拉函数-数学

Given the value of N, you will have to ?nd the value of G. The de?nition of G is given below:G =i<N∑i=1j∑≤Nj=i+1GCD(i, j)Here GCD(i, j) means the greatest common divisor of integer i and integer j.For those who have trouble understanding summation no

UVa 10820 (打表、欧拉函数) Send a Table

题意: 题目背景略去,将这道题很容易转化为,给出n求,n以内的有序数对(x, y)互素的对数. 分析: 问题还可以继续转化. 根据对称性,我们可以假设x<y,当x=y时,满足条件的只有(1, 1). 设f(n)为 集合S{(x, y) | x<y且x.y互素} 的个数,则所求答案为2f(n)+1 f(n)表达式为: ,其中φ(n)为欧拉函数 这里有欧拉函数的一些介绍 1 #include <cstdio> 2 3 const int maxn = 50000; 4 5 int ph

Uva 10820 Send a Table(欧拉函数)

对每个n,答案就是(phi[2]+phi[3]+...+phi[n])*2+1,简单的欧拉函数应用. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<map> #include<set> #include<list> #i

UVA 11426 GCD - Extreme (II) 欧拉函数

分析:枚举每个数的贡献,欧拉函数筛法 #include <cstdio> #include <iostream> #include <ctime> #include <vector> #include <cmath> #include <map> #include <queue> #include <algorithm> #include <cstring> using namespace std;

UVa 11426 GCD - Extreme (II) (欧拉函数应用&#183;O(N*logN))

题意  令  G(n) = sum{gcd(i, j) | 0 < i < n, i < j <= n}  给你一个n  输出G(n) 令 F(n) = sum{gcd(i, n) | 0 < i < n}  那么有递推式 G(n) = G(n-1) + F(n) , G(0)  = 0  也就是说只用求出F(n) 就能递推求出 G(n)了  而求F(n)就比较容易了 对于i  设 x < i , gcd(x,i) = 1 即x, n 互质 则  gcd(2*x,