算法入门经典:开灯问题
前言:一直很羡慕那些善于写算法的同学,感觉他们真的很聪明,不想我这么笨,一思考算法就头疼。罢了,从最简单的开始吧,加油。
问题:
有n盏灯,编号为1~n,第1个人把所有灯打开,第2个人按下所有编号为2的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯被打开, 开着灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?
输入:n和k,输出开着的灯编号。k≤n≤1000。
样例输入:
7 3
样例输出:
1 5 6 7
分析:
用 a[1],a[2],......,a[n] 表示编号为1,2,3,.......,n 的灯是否开着。
C语言实现:
//开灯问题
#include <stdio.h>
#include <string.h>
#define maxn 1010 //定义一个稍比1000大的数组
int a[maxn];
int main()
{
int n, k, first = 1; //n 盏灯,k 个人
memset(a, 0, sizeof(a)); //把a中元素置为0
scanf("%d%d",&n,&k);
for (int i = 1; i <= k; i++) //用i表示
for(int j = 1; j <=n; j++)
if(j % i == 0)
a[j] = !a[j];
for (int i = 1; i <= n; i++)
{
if(a[i]){
if(first)
first = 0;
else
printf(" ");
printf("%d",i);
}
}
printf("\n");
return 0;
}
输出技巧:
算法竞赛中,常常难以精确计算出需要的数组大小,一般会声明的稍大一些。
为了避免输出多余的空格,设置一个标志变量first,可以表示当前要输出的变量是否为第一个。第一个变量前不应有空格,但其他变量有。
附上我用C++实现的代码:
#include <iostream>
#include <string>
using namespace std;
const int maxn = 1010;
int main()
{
int n, k;
bool isFirst = true; //定义一个判断是否是第一位
bool a[maxn];
memset(a, false, sizeof(a)); //先定义false为关灯状态
cin>> n>> k;
for(int i = 1; i < k; i++)
for(int j = 1; j <= n; j++)
if(j % i == 0)
a[j] = !a[j];
for (int i = 1; i <= n; i++)
{
if(a[i]){
if(isFirst)
isFirst = false;
else
cout<< " ";
cout<< i;
}
}
cout<< endl;
return 0;
}