新年快到了,“猪头帮协会”准备搞一个聚会,已经知道现有会员N人,把会员从1到N编号,其中会长的号码是N号,凡是和会长是老朋友的,那么该会员的号码肯定和N有大于1的公约数,否则都是新朋友,现在会长想知道究竟有几个新朋友?请你编程序帮会长计算出来。
7680
16016
超时答案
#include<iostream>
using namespace std;
int gcd(int a, int b)
{
if (a < b)
{
int c = a;
a = b;
b = c;
}
return (a%b == 0) ? b : gcd(b, a%b);
}
int main()
{
int n,a,b,i,N;
cin >> n;
while (n--)
{
int count = 0;
cin >> N;
for (int i = 1; i < N; i++)
if (gcd(i, N) == 1)
count++;
cout << count << endl;
}
system("pause");
return 0;
}
以上答案超时,看到一个博客的解析很好
@梦小白 http://blog.csdn.net/qq_15096707/article/details/43310023?locationNum=9&fps=1
以下为博主原文:
首先读者可能会想:首先创建一个计数器count,从1到N-1编号将每个数均与N判断是否存在公约数,如果不存在公约数则count加1,即新朋友的数量加1。
用Java语言编写程序,代码可能结果如下:
- import java.util.*;
-
- public class Main1079a {
-
- public static void main(String[] args) {
-
- 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;
- 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) {
-
- Scanner input = new Scanner(System.in);
- int cn = input.nextInt();
- for(int i = 0; i < cn; i++) {
- int n = input.nextInt();
-
-
- 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++) {
-
- 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);
- }
- }
-
- }
但博主的代码不是很简洁
另外一个博主的代码很简洁
@
- http:
- <pre name="code" class="cpp">#include <stdio.h>
- #include <string>
- #define MAXN 32768
- int a[MAXN + 5];
- int main()
- {
- int i, j, k, CN, num, count;
- scanf("%d", &CN);
- while (CN--)
- {
-
- memset(a, 0, sizeof(a));
- scanf("%d", &num);
-
- for (j = 2; j < num; j++)
- if (num % j == 0)
- for (k = j; k < num; k += j)
- a[k] = 1;
- count = 0;
-
- for (k = 1; k < num; k++)
- if (a[k] == 0)
- count++;
- printf("%d\n", count);
- }
- }
编译错误,不知道怎么通过。。。
总结:编译错误可能就是格式上的问题或者写法虽然能运行出来,但是和这种语言不兼容的,所以换一种写法试试o(^▽^)o
- #include<iostream>
- using namespace std;
- const int MAXN = 32768;
- int arr[MAXN + 5];
- int main()
- {
- int n,i,j,N;
- cin >> n;
- while (n--)
- {
- for (i = 0; i < MAXN; i++)
- arr[i] = 0;//数组全部初始化为0
- int count = 0;
- cin >> N;
- for (i = 2; i < N; i++)
- if (N % i == 0)
- for (j = i;j < N;j += i)//比如N%2==0,那么将2,2+2,2+2+2,。。。全记为1,然后3,5,7。。。
- arr[j] = 1;
- for (i = 1;i<N;i++)
- if (arr[i] == 0)
- count++;
- cout << count << endl;
- }
- //system("pause");
- return 0;}
-
YEAH!
( •̀ ω •́ )y!!
AC!!!
*★,°*:.☆\( ̄▽ ̄)/$:*.°★*