uva 10820 poj 2407 poj 1284 poj 2478 poj 3090 (欧拉函数入门)

题意:

求满足小于等于n且互素的无序二元组(a, b)的组数。ps,无序,(2, 3)和(3, 2)算是两组。


解析:

做了这题明白了欧拉函数的用法。

欧拉函数,就是求小于一个数d且与d互素的数的个数。结果保存在phi[ d ]中。

放到这题,要求一个二元组,就是累加1到n的phi,由于无序 * 2,又因为(1, 1)和(1, 1)相同,所以-1。


代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long

using namespace std;
const int maxn = 50000 + 1;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);

int phi[maxn];
int sum[maxn];

void phi_table()
{
    for (int i = 2; i <= maxn; i++)
        phi[i] = 0;
    phi[1] = 1;
    for (int i = 2; i <= maxn; i++)
    {
        if (!phi[i])
        {
            for (int j = i; j <= maxn; j += i)
            {
                if (!phi[j])
                {
                    phi[j] = j;
                }
                phi[j] = phi[j] / i * (i - 1);
            }
        }
    }
}

void sum_table()
{
    sum[0] = 0;
    for (int i = 1; i <= maxn; i++)
    {
        sum[i] = sum[i - 1] + phi[i];
    }
}

int main()
{
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
    #endif // LOCAL
    phi_table();
    sum_table();
    int n;
    while (scanf("%d", &n) && n)
    {
        printf("%d\n", (sum[n] << 1) - 1);
    }
    return 0;
}


poj 2407:

题意:

求小于n且与n互素的正整数有多少。


解析:

求欧拉函数O(n)的算法。


代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long

using namespace std;

int euler_phi(int n)
{
    int m = sqrt(n + 0.5);
    int res = n;
    for (int i = 2; i <= m; i++)
    {
        if (n % i == 0)
        {
            res = res / i * (i - 1);
            while (n % i == 0)
                n /= i;
        }
    }
    if (1 < n)
        res = res / n * (n - 1);
    return res;
}

int main()
{
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
#endif // LOCAL
    int n;
    while (scanf("%d", &n) && n)
    {
        printf("%d\n", euler_phi(n));
    }
    return 0;
}

poj 1284:

题意:

给一个奇素数p (3 <= p < 65536)。

当集合 { (x ^ i mod p ) | 1 <= i <= p - 1 } . 与集合 { 1,…,p - 1}, 相同时,整数x(0 < x < p)是奇素数p的原根。

输入p,求p原根的个数。


解析:

原根的个数为 ans =  phi(phi(p)),因为phi(p) = p - 1,所以 ans = phi(p - 1)。


代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long

using namespace std;

int euler_phi(int n)
{
    int m = sqrt(n + 0.5);
    int res = n;
    for (int i = 2; i <= m; i++)
    {
        if (n % i == 0)
        {
            res = res / i * (i - 1);
            while (n % i == 0)
                n /= i;
        }
    }
    if (1 < n)
        res = res / n * (n - 1);
    return res;
}

int main()
{
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
#endif // LOCAL
    int n;
    while (scanf("%d", &n) == 1)
    {
        printf("%d\n", euler_phi(n - 1));
    }
    return 0;
}

poj 2478:

题意:

根据法雷级数的定义,求法雷级数 Fn 中共有几个元素。

法雷级数Fn (2 <= n)是由一系列不能约分的分数 a / b (0 < a < b <= n && gcd(a, b ) == 1)按递增序列组成。


解析:

一个法雷序列Fn中的个数就是分别与 2,3,4,5,6......,n - 1,n互素的数的个数和。


代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long

using namespace std;
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);

LL phi[maxn];
LL sum[maxn];

void phi_table()
{
    for (int i = 1; i <= maxn; i++)
        phi[i] = i;
    for (int i = 2; i <= maxn; i += 2)
        phi[i] >>= 1;
    for (int i = 3; i <= maxn; i += 2)
    {
        if (phi[i] == i)
        {
            for (int j = i; j <= maxn; j += i)
                phi[j] = phi[j] / i * (i - 1);
        }
    }
}

void sum_table()
{
    sum[0] = 0;
    for (int i = 1; i <= maxn; i++)
    {
        sum[i] = sum[i - 1] + phi[i];
    }
}

int main()
{
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
    #endif // LOCAL
    phi_table();
    sum_table();
    int n;
    while (scanf("%d", &n) && n)
    {
        printf("%lld\n", sum[n] - 1);
    }
    return 0;
}

poj 3090:

题意:

同第一题,求小与n的x,y互素有多少组。


解析:

与uva那题不同的是,uva那题要-掉多算的 (1,1)的情况,而这题不能漏掉(1,1),(1,0),(0,1)这三种情况,所以+1就行了。

还有一点不同就是这里打表用了O(nlogn)的算法,不然TLE。


代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long

using namespace std;
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);

LL phi[maxn];
LL sum[maxn];

///O(nlogn)
void phi_table()
{
    for (int i = 1; i <= maxn; i++)
        phi[i] = i;
    for (int i = 2; i <= maxn; i += 2)
        phi[i] >>= 1;
    for (int i = 3; i <= maxn; i += 2)
    {
        if (phi[i] == i)
        {
            for (int j = i; j <= maxn; j += i)
                phi[j] = phi[j] / i * (i - 1);
        }
    }
}

void sum_table()
{
    sum[0] = 0;
    for (int i = 1; i <= maxn; i++)
    {
        sum[i] = sum[i - 1] + phi[i];
    }
}

int main()
{
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
    #endif // LOCAL
    phi_table();
    sum_table();
    int ncase;
    int ca = 1;
    scanf("%d", &ncase);
    while (ncase--)
    {
        int n;
        scanf("%d", &n);
        printf("%d %d %lld\n", ca++, n, (sum[n] << 1) + 1);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值