poj 2478/3090 欧拉函数应用(Farey 序列/斜率判重)

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值