Enumerating Rational Numbers UVA - 11327 欧拉函数
欧拉函数
题目链接:https://vjudge.net/problem/UVA-11327
题意:
for d = 1 to infinity do
for n = 0 to d do
if gcd(n,d) = 1 then print n/d
按分母从小到大顺序,输出第k个最简真分数(即分子分母互质 && 分子小于等于分母)
注意:特殊的,第一个为0/1,第二个为1/1;
数列为:0/1, 1/1, 1/2, 1/3, 2/3, 1/4, 3/4, 1/5, 2/5, 3/5, 4/5, 1/6, 5/6, 1/7, . . .
题解:
打表欧拉函数,记录前缀和。利用分组查找,先通过二分查找得出第n个数属于哪个分母范围内的,再通过暴力枚举与该分母互质的合理分子。
特别要处理当分母为1时,分子可以为0,1
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 #define N 2000005 // 由样例可知最大数组范围为200000 6 #define ll long long 7 8 ll oula[N]; //记录欧拉函数 9 ll sum[N]; //记录前缀和 10 11 int euler_phi(int n) { //计算欧拉函数 12 int ans = n; 13 for (int i = 2; i * i <= n; i++) { 14 if (n % i == 0) { 15 ans = ans / i * (i - 1); 16 while (n % i == 0) 17 n /= i; 18 } 19 } 20 if (n > 1) 21 ans = ans / n * (n - 1); 22 return ans; 23 } 24 25 void init() { //计算前缀和 26 sum[0] = oula[0] = 0; 27 oula[1] = 2;sum[1] = 2;//特别处理分母为1的情况 28 for (int i = 2; i < N; i++) { 29 oula[i] = euler_phi(i); 30 sum[i] = sum[i - 1] + oula[i]; 31 } 32 } 33 34 35 int gcd(int a, int b) { 36 return b == 0 ? a : gcd(b, a % b); 37 } 38 39 void solve(ll num, int x) { //查找分母为x时,第num个分子,打印输出分数 40 int i; 41 if (x == 1) { //特别处理分母为1的情况 42 num--; 43 i = 0; 44 } 45 for (i = 1; i <= x && num; i++) { 46 if (gcd(i, x) == 1) { 47 num--; 48 } 49 } 50 printf("%d/%d\n", i - 1, x); 51 } 52 53 int main() { 54 ll n; 55 init(); 56 while (scanf("%lld", &n) && n != 0) { 57 int x = upper_bound(sum, sum + N, n) - sum; //返回大于n的第一个元素下标 58 int y = lower_bound(sum, sum + N, n) - sum; //返回不小于n的第一个元素下标 59 if (x != y) //处理边界情况,确保x始终为分母大小 60 x--; 61 ll temp = n - sum[x - 1]; //在分母为x的这个区间里,属于第几个 62 solve(temp, x); 63 } 64 return 0; 65 }
我一定很聪明,但不会绝顶,这是我最后的倔强!!!

浙公网安备 33010602011771号