一.题目
有n盏灯,编号为1~n,第1个人把所有灯打开,第2个人按下所有编号为2的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯被打开, 开着灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?
输入:n和k,输出开着的灯编号。k≤n≤1000。
样例输入:7 3
样例输出:1 5 6 7
二.思路
看到这个问题,我继续想尝试昨天的dfs,看了看情况,感觉可以…;要是没有dfs的话,那就直接双重循环解决问题…
三. 代码
第一种,dfs:
#include <stdio.h>
int book[1001];
void dfs(int step,int k,int n)
{
int j;
if(step == k+1)
{
int i;
for(i=1;i<=n;i++)
{
if(book[i]==1)
{
printf("%d ",i);
}
}
return ;
}
for(j=step;j<=n;j++) //灯
{
int i;
if(j%step==0)
{
if(book[j]==0) book[j]=1;
else book[j]=0;
}
}
dfs(step+1,k,n); //这里的递归要在for外面进行,因为它不是要一直在循环内的。
}
int main ()
{
int n,k;
scanf("%d%d",&n,&k);
dfs(1,k,n);
return 0;
}
第二种,双重循环解决问题
#include <stdio.h>
int a[1001];
int main ()
{
int n,k;
scanf("%d%d",&n,&k);
int i,j;
for(i=1;i<=k;i++)
{
for(j=1;j<=n;j++)
{
if(j%i==0) a[j] = !a[j]; //这一步直接用 !,十分省事,也很巧妙
}
}
for(i=1;i<=n;i++)
{
if(a[i]) {printf("%d ",i);}
}
return 0;
}
四.总结:
书本上提供的代码有两个小技巧:
1. 利用memset(a,0,sizeof(a)); 进行全部赋值
2. 利用标志变量来控制要不要空格