SGU 102 Coprimes

裸的欧拉函数……

暴力搜索也可以过……

(代码写的很水很水很水,不要看!)

欧拉函数版
/*************************************************************************
    > File Name:    sgu102.cpp
    > Author:       Shine
    > Created Time: 2013-05-04 上午 6:36:05
    > QuestionType: 欧拉函数
    > Way: 
    > Submit: 
    > Gain: 
    > Experience: 
 ************************************************************************/
#include <cstdio>
#include <cstring>
#include <cmath>

int yz[10010][6] = {0};

void predo() {
    int i;
    for (i = 2; i < 10000; i++) {
        if (yz[i][0] == 0) {
            int &p = yz[i][0];
            yz[i][++p] = i;
            int j;
            for (j = 2; i*j<=10000; j++) {
                int &p = yz[i*j][0];
                yz[i*j][++p] = i;
            }
        }
    }
}


int main() {
    predo();
    int n;
    while (scanf("%d", &n)!=EOF) {
        int i;
        double num = n;
        for (i = 1; i <= yz[n][0]; i++) {
            num = num *(1.0-1.0/yz[n][i]);
        }
        printf("%.0llf\n", num);
     }

    return 0;
}
暴力搜索版
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define min(a,b) ((a)<(b)?(a):(b))

int kgcd(int a, int b){ 
    if (a == 0) return b; 
    if (b == 0) return a; 
    if (!(a & 1) && !(b & 1)) return kgcd(a>>1, b>>1) << 1;
    else if (!(b & 1)) return kgcd(a, b>>1); 
    else if (!(a & 1)) return kgcd(a>>1, b); 
    else return kgcd(abs(a - b), min(a, b)); 
} 

int main() {
    int n;
    while(scanf("%d", &n) != EOF)  {
        int i;
        int num = 1;
        for (i = 2; i < n; i++) {
            if (kgcd(i,n) == 1) num++;
        }
        printf("%d\n", num);
    }
    return 0;
}

为什么欧拉函数版本写成这样?因为我AC的思路是:

求出每个数所有因子,然后不可行的个数sum = n/一个因子 - n/ 两个因子数积 + n/ 三个因子的积 - ……

因为输出过,最多5个因子,然后又想不到什么好的写法,所以很暴力的写成了这么多层循环……

因子商 求和 去重版
#include <cstdio>
#include <cstring>
#include <cmath>

int yz[10010][6] = {0};
int re[10010] = {0};

void predo() {
    int i;
    for (i = 2; i < 10000; i++) {
        if (yz[i][0] == 0) {
            int &p = yz[i][0];
            yz[i][++p] = i;
            int j;
            for (j = 2; i*j<=10000; j++) {
                int &p = yz[i*j][0];
                yz[i*j][++p] = i;
            }
        }
    }
}


int main() {
    predo();
    int n;
    while (scanf("%d", &n)!=EOF) {
        if (re[n]) printf("%d\n", re[n]);
        else {
            int i;
            int sum = 0;
            for (i = 1; i <= yz[n][0]; i++) {
                sum += n/yz[n][i];
            }
            int j;
            for (i = 1; i <= yz[n][0]-1; i++) {
                for (j = i+1; j <= yz[n][0]; j++) {
                    sum -= n / (yz[n][i]*yz[n][j]);
                }
            }
            int k;
            for (i = 1; i <= yz[n][0]-2; i++) {
                for (j = i+1; j <= yz[n][0]-1; j++) {
                    for (k = j+1; k <= yz[n][0]; k++) {
                        sum += n/(yz[n][i]*yz[n][j]*yz[n][k]);
                    }
                }
            }

            int l;
            for (i = 1; i <= yz[n][0]-3; i++) {
                for (j = i+1; j <= yz[n][0]-2; j++) {
                    for (k = j+1; k <= yz[n][0]-1; k++) {
                        for(l = k+1; l <= yz[n][0]; l++) {
                            sum -= n/(yz[n][i]*yz[n][j]*yz[n][k]*yz[n][l]);
                        }
                    }
                }
            }

            if (yz[n][0] == 5) sum += n/(yz[n][1]*yz[n][2]*yz[n][3]*yz[n][4]*yz[n][5]);

            printf("%d\n", re[n]=n-sum);
        }
        
    }

    return 0;
}

对于这种式子,不知道有没有人有更好的写法。。有的话请留个练习方式或者评论回复我都可以~感谢哦~

posted on 2013-05-05 21:54  ShineCheng  阅读(185)  评论(0编辑  收藏  举报

导航