注:如果觉得有问题,可以一起讨论哦
问题:有n盏灯,编号为1~n,第一个人把所有的灯打开,第二个人按下所有编号为2的倍数的开关(这些灯将被关掉),第三个人按下所有编号为3的倍数的开关(期中关掉的将被打开,打开的将被关掉)依此类推,一共有k个人,问最后有哪些灯开着,输入n和k,输出开着的灯的编号。k<=n<=1000
样例输入:
7 3
样例输出:
1 5 6 7
【分析】:用数组flag[],flag[0],flag[1],flag[2]....flag[n]表示灯1,2,3.。。。n是否开着。首先将他们全置为0,表示他们都开着,1则表示关了灯。
用例子来分析,7盏灯,3个人
因为flag[i]是会动态改变的,所以解题关键就是如何动态的去改变flag[i]的值
由图所见它和((i+1)%j==0)有关,如果i能整除j,那么flag[i]原来的值就要改变。
假设int a=((i+1)%j==0))=1
当j=2时,flag[2]由0变为1,flag[4]由0变为1,flag[6]由0变为1
当j=3时,flag[3]由0变为1,flag[6]由1变为0。
flag[i]到底和a有着什么样的关系?不难想象,他们是异或关系。
即flag[i]=((i+1)%j) xor flag[i]。
那我们要怎么样在代码中表示异或呢?
我们除了要判断i是否整除j,还要判断它是否和flag[i]的值是否一样,如果不一样,flag[i]就置1。
为了结果之间加空格,所以加了一个变量d,第一个结果肯定不能有空格,所以初始化d=0;当d=0时,不输出空格。d不等于0,就输出空格。
输入第一个结果后,d++;
所以代码很简单
/**开灯问题**/
#include "stdafx.h"
#include <string.h>
#define maxn 1010
int flag[maxn];
int _tmain(int argc, _TCHAR* argv[])
{
int n,k,d=0;
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
flag[i]=0;//打开
//printf("%d\n",flag[i]);
for(int j=2;j<=k;j++){
if((i+1)%j==0){
if(((i+1)%j==0)==flag[i])flag[i]=0;
else flag[i]=1;
}
//printf("%d[%d]:%d\n",j,i,flag[i]);
}
//结果之间加空格
if(flag[i]==0){
if(d==0){printf("%d",i+1);d++;}
else printf(" %d",i+1);
}
}
printf("\n");
return 0;
}