找新朋友

1079:找新朋友 分数:1

时间限制:1 秒
内存限制:32 兆
特殊判题:


标签

  • 简单数学题
  • 公约数

题目描述

新年快到了,天勤准备搞一个聚会,已经知道现有会员N人,把会员从1到N编号,其中会长的号码是N号,凡是和会长是老朋友的,那么该会员的号码肯定和N有大于1的公约数,否则都是新朋友,现在会长想知道究竟有几个新朋友?请你编程序帮会长计算出来。

输入格式

第一行是测试数据的组数CN(Case number,1<CN<10000),接着有CN行正整数N(1<n<32768),表示会员人数。

输出

对于每一个N,输出一行新朋友的人数,这样共有CN行输出。

样例输入

2
25608
24027

样例输出

7680
16016

       首先读者可能会想:首先创建一个计数器count,从1到N-1编号将每个数均与N判断是否存在公约数,如果不存在公约数则count加1,即新朋友的数量加1。

用java语言编写程序,代码可能结果如下:

import java.util.*;

public class Main1079a {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner input = new Scanner(System.in);
		int cn = input.nextInt();
		for(int i = 0; i < cn; i++) {
			int n = input.nextInt();
			int num = n - 1;//除去本身
			if(n % 2 == 0) {
				num = num - (n - 2) / 2;//除去那些与编号N有公约数2的编号
				for(int j = 1; j < n; j += 2) {
					//判断两数是否存在公约数
					if(isExistGcd(j, n))
						num -= 1;
				}
			}
			else {
				for(int j = 1; j < n; j++) {
					if(isExistGcd(j, n))
						num -= 1;
				}
			}
			System.out.println(num);
		}
	}
	
	public static boolean isExistGcd(int a, int b) {
		for(int i = 2; i <= a && i <= b; i++) {
			if(a % i == 0 && b % i == 0)
				return true;
		}
		return false;
	}
}

       聪明的读者可能已经发现,这样的程序效率很低,以至于系统会提示时间超限。(我还没提交过,感觉会超限)
那么,为了提高效率,我们可以采取类似”筛法求素数“的过程,首先将创建一个boolean类型的数组people(数组内所有值初始化为false),表明与会长的关系,如:people[10] = true;表示编号为10的会员是会长的老朋友;people[21] = false;表示编号为21的会员是会长的新朋友。

如果编号N能被2整除,则N与2以及2的倍数有公约数,那么就可以将people数组下标为2、2的倍数的值赋值为true;同样地,判断是否能被3、5、。。。整除。将所有与N有公约数的值赋值为true,计算数组中false值的个数,即为会长新朋友的人数。

用java语言编写程序,代码如下:

import java.util.Scanner;

public class Main1079b {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner input = new Scanner(System.in);
		int cn = input.nextInt();
		for(int i = 0; i < cn; i++) {
			int n = input.nextInt();
			//创建数组,并初始化为false。
			//该数组中的下标表示对应的编号,数组的值表示与会长的关系。true为老朋友,false为新朋友
			boolean people[] = new boolean[n];
			for(int j = 0; j < n; j++)
				people[j] = false;
			
			int num = 0;
			for(int j = 2; j <= n / 2; j++) {
				//标记与N有公约数的下标,赋值为true
				if(n % j == 0 && people[j] == false) {
					for(int k = j; k < n; k += j) {
						people[k] = true;
					}
				}
			}
			
			//计算新朋友的个数
			for(int j = 1; j < n; j++)
				if(people[j] == false)
					num++;
			System.out.println(num);
		}
	}

}



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值