且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

开灯关灯问题

更新时间:2022-08-16 19:18:31

来源:http://www.cnblogs.com/haolujun/archive/2012/10/10/2719031.html

作者:haolujun

有编号1~100个灯泡,起初所有的灯都是灭的。有100个同学来按灯泡开关,如果灯是亮的,那么按过开关之后,灯会灭掉。如果灯是灭的,按过开关之后灯会亮。

现在开始按开关。

第1个同学,把所有的灯泡开关都按一次(按开关灯的编号: 1,2,3,......100)。
第2个同学,隔一个灯按一次(按开关灯的编号: 2,4,6,......,100)。
第3个同学,隔两个灯按一次(按开关灯的编号: 3,6,9,......,99)。
......

问题是,在第100个同学按过之后,有多少盏灯是亮着的?

这个问题有一个数学上的解决方法。可以看出,被按了奇数次的灯泡应该是亮着的,被按了偶数次的灯泡应该是灭的。那么什么样的灯泡被按了奇数次?什么 样的灯泡又被按了偶数次呢?从按的过程可以发现,如果一个灯泡的编号具有偶数个因子,那么该灯泡就被按了偶数次,反之按了奇数次。现在的问题又变成,什么 样的编号具有奇数个因子,什么样的编号具有偶数个因子?这涉及到一个叫做质因数分解的定理,大概的意思是说,任何正数都能被唯一表示成多个质因数幂次乘积 的方式。

例如:

14=2*7
50=2*5^2
...
100=2^2*5^2

也就是N=(p[1]^e[1])*(p[2]^e[2])*......*(p[k]^e[k]),其中p[i]是质数,e[i]是p[i]的幂次。而由这个公式我们又可以导出一个数有多少个因子的计算公式:FactorNumber(N)=(e[1]+1)*(e[2]+1)*......*(e[k]+1)。

那么什么条件下满足FactorNumber(N)是奇数呢?显然必须所有的e[1],e[2],......,e[k]都必须是偶数,这样才能保证e[i]+1是奇数,结果乘积才能是奇数。而由于e[1],e[2],......,e[k]都是偶数,那么N一定是一个完全平方数(因为sqrt(N)=(p[1]^(e[1]/2))*(p[2]^(e[2]/2))*......*(p[k]^(e[k]/2))是整数) 。回到按灯泡的问题上来,1~100中完全平方数有1,4,9,16,25,36,49,64,81,100这10个数,也就是说最后只有编号为这10个数的灯是亮着的。

 

 

 

相类似题目:http://blog.csdn.net/oceaniwater/article/details/40709609

 

 有n盏灯,编号为1~n,第1个人把所有灯打开,第2个人按下所有编号为2的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯被打开,       开着灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?

    输入:n和k,输出开着的灯编号。k≤n≤1000。

 

   样例输入:7  3

 

   样例输出:1 5 6 7

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #define MAXN 1000 + 10
 5 int a[MAXN];
 6 
 7 int main(int argc, char *argv[])
 8 {
 9   int i, j, n, k, first = 1;
10   scanf("%d %d", &n, &k);
11   memset(a, -1, sizeof(a));
12   for(i = 1; i <= k; i++)
13      for(j = 1; j <= n; j++)
14      {
15         if(j%i == 0) a[j] = -a[j];
16      }
17      /* 
18   for(j = 1; j <= n; j++)
19      if(a[j] == 1) printf("%d ", j); //最后应该没空格 
20        
21        */   
22                               
23   for(j = 1; j <= n; j++)
24      if(a[j] == 1) {if(first) first = 0; else printf(" "); printf("%d", j);}
25   printf("\n");     //最后再输出换行符 
26   system("PAUSE");    
27   return 0;
28 }

总结:1. 用一个标志来判断是否为第一次输出,如是,不输出空格,否则先输空格后输数字

        2 开关灯也可以用0 1