欧拉函数ϕ(n)是不超过n且和n互质的正整数的个数。
下面直观地看看欧拉函数:
n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
φ(n) | 1 | 1 | 2 | 2 | 4 | 2 | 6 | 4 | 6 | 4 | 10 | 4 | 12 | 6 | 8 |
定理
- 定理0 算术函数f如果满足对于任意两个互质的正整数m和n,均有f(mn)=f(m)f(n),就称f为积性函数(或乘性函数)。
如果对于任意两个正整数m和n,均有f(mn)=f(m)f(n),就称为完全积性函数。
- 定理1 对于素数p,ϕ(p)=p−1。
- 定理2 ϕ(pn)=pn−pn−1,因为素数幂pn不互质的只有p的倍数,一共有pn/p=pn−1个。
- 定理3 若m、n互质,ϕ(mn)=ϕ(m)ϕ(n),所以欧拉函数是积性函数。
因为mn互质,和m互质的数乘上和n互质的数就会和mn互质。
- 定理4 设n=p1a1p2a2...pkak为正整数n的素数幂分解,那么ϕ(n)=n(1−1/p1)(1−1/p2)...(1−1/pk)。
由定理2,ϕ(pn)=pn−pn−1=pn (1-1/p),又由定理3,ϕ(n)=p1a1p2a2...pkak(1−1/p1)(1−1/p2)...(1−1/pk)=n(1−1/p1)(1−1/p2)...(1−1/pk)
由定理4得到的代码如下:
int euler(int x){
int res = x;
for(int i=2; i*i<=x; i++)
if(x % i == 0)
{ res = res / i * (i - 1);
while(x % i == 0) x /= i;
}
if(x > 1) res = res / x * (x - 1);//防止溢出。
return res;
}
(好长好长时间才差不多明白的一个算法,心塞啊)
认识了欧拉函数,与本题的关系在哪里,想啊想,怎么联系这个呢?思路受限制,怎么用怎么用??
最终还是躲不过看题解了。(水题)
做法:所求个数等于由(0,0)点与其他两点所组三角形个数*2+1
三角形个数怎么求?
依次计算每层所增加符合题意的三角形个数,求和,即 依次求每多一层时,新增加的斜率的个数,而新增的斜率的个数正好是以该层边长为变量的欧拉函数的值。
So,代码如下:
int euler(int x){
int res = x;
for(int i=2; i*i<=x; i++)
if(x % i == 0){
res = res / i * (i - 1);
while(x % i == 0) x /= i;
}
if(x > 1) res = res / x * (x - 1);
return res;
}
int main()
{
int C,N;
while (scanf("%d", &C) != EOF)
{
for (int i = 0; i < C; ++ i)
{
scanf("%d", &N);
int sum = 0;
for (int j = 1; j <= N ; ++ j )
{
sum += euler(j);
}
printf("%d %d %d\n", i + 1, N, 2 * sum + 1);
}
}
return 0;
}
(心情简单??!!!)
1)所有的奇素数都是有原根的
2)一个数n有原根,那么他有phi(phi(n))个模n不同余的原根(n是否素数都可用)