2478题意:求Farey序列。Fn定义为:对于0 < a < b <= n,求a/b的个数,其中a与b互质。如
F2 = {1/2}
F3 = {1/3, 1/2, 2/3}
F4 = {1/4, 1/3, 1/2, 2/3, 3/4}
F5 = {1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5}
思路:使用欧拉函数。欧拉函数是指,对于一个正整数n,小于n且和n互质的正整数(包括1)的个数,记作φ(n) 。通式:φ(x)=x*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)…..(1-1/pn),其中p1, p2……pn为x的所有质因数。φ(1)=1(唯一和1互质的数就是1本身)。对于质数p,φ(p) = p - 1。注意φ(1)=1.
3090题意:n*n个点,要从源点往这些点连线,问没有被其他点盖住的点有多少。例如(4,2)就无法到达,因为(2,1)挡住了它。
用欧拉函数也可以解决,因为没有被挡住的点只有两个数是互质的情况。根据对称性,只求出一半来即可,最后的加1加的是(1,1)那个点。
2478:
#include <stdio.h>
#include <string.h>
#define N 1000001
int s[N];
int n;
__int64 res[N];
void init(){
int i,j;
memset(res,0,sizeof(res));
memset(s,0,sizeof(s));
for(i = 2;i<N;i++){
if(!s[i]){
for(j = i;j<N;j+=i){
if(!s[j])
s[j] = j;
s[j] = s[j]/i*(i-1);
}
}
}
for(i = 2;i<N;i++)
res[i] = res[i-1]+s[i];
}
int main(){
freopen("a.txt","r",stdin);
init();
while(scanf("%d",&n) && n)
printf("%I64d\n",res[n]);
return 0;
}
3090:
#include <cstdio>
#include <cstring>
#include <set>
#include <cmath>
using namespace std;
#define clr(s,t) memset(s,t,sizeof(s))
#define N 1005
int T,n,s[N];
void init(){
int i,j;
clr(s, 0);
s[1] = 1;
for(i = 2;i<=1000;i++)
if(!s[i])
for(j = i;j<=1000;j+=i){
if(!s[j])
s[j] = j;
s[j] = s[j]/i*(i-1);
}
}
int main(){
scanf("%d",&T);
init();
for(int c = 1;c<=T;c++){
int res = 0;
scanf("%d",&n);
for(int i = 1;i<=n;i++)
res += s[i];
printf("%d %d %d\n",c,n,1+(res<<1));
}
return 0;
}