题意:
求满足小于等于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;
}