zoukankan      html  css  js  c++  java
  • poj2478 ——欧拉函数入门题

    题目链接:http://poj.org/problem?id=2478

    题目大意:

      给你一个数列f(N),这个数列是由一系列不能约分的分数 a / b (0 < a < b <= n 且 (a,b) = 1)按照递增的顺序排列而成的。输入一个N,求这个数列中元素的个数。

    题目思路:

      因为题目只需要求出元素的个数,所以,把分母相同的放在一起,然后就发现规律了,其实就是求从2到 n 的欧拉函数的和。范围只有10^6,可以打表预处理。思路很清晰。因为要反复用欧拉函数,所以比较快的方法是用递推的方法求。

      

    1   for (i = 1; i <= maxn; ++i) f[i] = i;
    2   for (i = 2; i <= maxn; i+=2) f[i] /= 2;
    3   for (i = 3; i <= maxn; i+=2){
    4     if (f[i] == i){
    5       for (j = i; j <= maxn; j+=i){
    6         f[j] = f[j] / i * (i - 1);
    7       }
    8     }
    9   }

      

      这个方法和筛法求素数比较类似,貌似就是那个思想。模拟一下什么就懂了。这里也用到了欧拉函数的性质:φ(n) = n * (1 - 1/p1) * (1 - 1/p2) * …… * (1 - 1/pk)。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cctype>
     6 #include <stack>
     7 #include <queue>
     8 #include <map>
     9 #include <set>
    10 #include <vector>
    11 #include <cmath>
    12 #include <algorithm>
    13 #define lson l, m, rt<<1
    14 #define rson m+1, r, rt<<1|1
    15 using namespace std;
    16 typedef long long int LL;
    17 const int MAXN =  0x3f3f3f3f;
    18 const int  MIN =  -0x3f3f3f3f;
    19 const double eps = 1e-9;
    20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
    21   {1,1},{1,-1},{-1,-1}};
    22 
    23 const int maxn = 1000000+10;
    24 int f[maxn];
    25 int main(void){
    26 #ifndef ONLINE_JUDGE
    27   freopen("poj2478.in", "r", stdin);
    28 #endif
    29 
    30   LL i, j;
    31   for (i = 1; i <= maxn; ++i) f[i] = i;
    32   for (i = 2; i <= maxn; i+=2) f[i] /= 2;
    33   for (i = 3; i <= maxn; i+=2){
    34     if (f[i] == i){
    35       for (j = i; j <= maxn; j+=i){
    36         f[j] = f[j] / i * (i - 1);
    37       }
    38     }
    39   }
    40   //printf("%d\n", f[5]);
    41   //for (i = 2; i <= 14; ++i) printf("f[%d] = %d\n", i, f[i]);
    42   //for (i = 2; i <= 14; ++i) printf("f[] = %d\n", f[i]);
    43   int n;
    44   while (~scanf("%d", &n)){
    45     if (!n) break; LL ans = 0;
    46     for (i = 2; i <= n; ++i){
    47       ans += f[i]; //printf("f[%d] = %d ", i, f[i]);
    48     }
    49     printf("%lld\n", ans);
    50   }
    51 
    52   return 0;
    53 }

      写代码的时候还是遇到了一些问题,比如把改写成 j 的地方写成了 i ,还好很快找到了,以后这种错误从一开始就不要犯。

      调试的时候发现一个很神奇的现象,不能解释啊。41行的注释,输出来 f[i] 的值都是0!42行的注释输出来就是正常的!好吧,原因到现在我还不知道……貌似是语言的细节?希望神牛路过指点啊~

      另外,求的时候,没有必要每次都加一遍,也可以把f[]数组进一步处理,让f[n]保存前n项得欧拉函数的和,这样就可以直接输出f[n]的值了。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cctype>
     6 #include <stack>
     7 #include <queue>
     8 #include <map>
     9 #include <set>
    10 #include <vector>
    11 #include <cmath>
    12 #include <algorithm>
    13 #define lson l, m, rt<<1
    14 #define rson m+1, r, rt<<1|1
    15 using namespace std;
    16 typedef long long int LL;
    17 const int MAXN =  0x3f3f3f3f;
    18 const int  MIN =  -0x3f3f3f3f;
    19 const double eps = 1e-9;
    20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
    21   {1,1},{1,-1},{-1,-1}};
    22 
    23 const int maxn = 1000000+10;
    24 LL f[maxn];
    25 int main(void){
    26 #ifndef ONLINE_JUDGE
    27   freopen("poj2478.in", "r", stdin);
    28 #endif
    29 
    30   LL i, j;
    31   for (i = 1; i <= maxn; ++i) f[i] = i;
    32   for (i = 2; i <= maxn; i+=2) f[i] /= 2;
    33   for (i = 3; i <= maxn; i+=2){
    34     if (f[i] == i){
    35       for (j = i; j <= maxn; j+=i){
    36         f[j] = f[j] / i * (i - 1);
    37       }
    38     }
    39   }
    40   for (i = 3; i <= maxn; ++i){
    41     f[i] += f[i-1];
    42   }
    43   //printf("%d\n", f[5]);
    44   //for (i = 2; i <= 14; ++i) printf("f[%d] = %d\n", i, f[i]);
    45   //for (i = 2; i <= 14; ++i) printf("f[] = %d\n", f[i]);
    46   int n;
    47   while (~scanf("%d", &n)){
    48     if (!n) break; LL ans = 0;
    49     /*
    50     for (i = 2; i <= n; ++i){
    51       ans += f[i]; //printf("f[%d] = %d ", i, f[i]);
    52     }
    53     */
    54     printf("%lld\n", f[n]);
    55   }
    56 
    57   return 0;
    58 }

      速度快了一点儿~这种预处理的方法学习一下。

  • 相关阅读:
    .net中连接远程目录的解决方案
    VS2008+Window Mobile开发环境的搭建(转)
    安装任何版本ActiveSync都出错原因
    问题让人开始慢慢的思考
    [原创]EasyUI的TreeGrid查询功能实现
    听客户说然后再做开发
    EasyUI的DataGrid合击汇总页脚使用教程
    ASP.NET MVC 使用AderTemplate模板引擎进行视图显示
    C#的JSON数据格式转换方法
    Delphi使用ReportMachine制作小计和总计报表
  • 原文地址:https://www.cnblogs.com/liuxueyang/p/3035301.html
Copyright © 2011-2022 走看看