例17   百灯判亮

问题描述

有序号为1、2、3、…、99、100的100盏灯从左至右排成一横行,且每盏灯各由一个拉线开关控制着,最初它们全呈关闭状态。有100个小朋友,第1位走过来把凡是序号为1的倍数的电灯开关拉一下;接着第2位小朋友走过来,把凡是序号为2的倍数的电灯开关拉一下;第3位小朋友走过来,把凡是序号为3的倍数的电灯开关拉一下;如此下去,直到第100个小朋友把序号为100的电灯开关拉一下。问这样做过一遍之后,哪些序号的电灯是亮着的?

输入格式

每行测试数据是一个正整数n,代表第n盏灯。

输出格式

每行输出第n盏灯的状态,0代表灯是熄灭的,1代表灯是亮的。

输入样例

1

5

输出样例

1

0

(1)编程思路1。

要判定哪些序号的灯是亮的,需要知道100个小朋友操作过后,每盏灯的拉线开关被拉的次数,这样凡是被拉了奇数次开关的灯最后就是亮的。

为了保存每盏灯的拉线开关被拉的次数,需要定义一个一维数组int  a[101];用数组元素a[1]~a[100]保存1~100号灯的开关被拉的次数(初始值为0,表示开关没有被拉1次)。

程序用一个二重循环来模拟小朋友的操作过程。外循环控制小朋友从1~100,对于第i个小朋友,他拉第i、2i、3i…号灯的拉线开关的操作构成内循环。具体描述为:

for (child=1;child<=100;child++)               // 小朋友从1~100

for (lamp=child;lamp<=100;lamp+=child)    // 第i个小朋友从第i号灯开始操作

a[lamp]++;

经过循环模拟小朋友拉开关的动作后,判定元素a[i]的奇偶性,如果a[i]为奇数,则第i盏灯是亮的。

(2)源程序1。

#include <stdio.h>

int main()

{

int a[101],child,lamp;     // a[1]~a[100]保存1~100盏灯的开关被拉的次数

for (lamp=0;lamp<=100;lamp++)

a[lamp]=0;

for (child=1;child<=100;child++)

for (lamp=child;lamp<=100;lamp+=child)

a[lamp]++;

int n;

while (scanf("%d",&n)!=EOF)

{

if (a[n]%2)

printf("1\n");

else

printf("0\n");

}

return 0;

}

(3)编程思路2。

实际上,除了采用思路1的方式用数组直接模拟外,本例还可以这样做。

我们知道,第n盏灯的拉线开关只会由编号为其约数的小朋友拉一下。例如,第24盏灯,会由编号分别为1、2、3、4、6、8、12、24的小朋友拉一下,它被拉了偶数次,故它最终是熄灭的。

更一般地,对于第n盏灯,若n=i*j,则一定有编号为i的小朋友的操作将灯由0变成1,编号为j的小朋友的操作会将灯由1变成0。最后,当且仅当n=i*i时,灯是亮的。

因此,本题实质是判断n是否是完全平方数即可。

(4)源程序2。

#include <stdio.h>

#include <math.h>

int main()

{

int n,k;

while (scanf("%d",&n)!=EOF)

{

k=(int)sqrt(1.0*n);

if (k*k==n)

printf("1\n");

else

printf("0\n");

}

return 0;

}

习题17

17-1  THE DRUNK JAILER

本题选自北大POJ题库(http://poj.org/problem?id=1218)

Description

A certain prison contains a long hall of n cells, each right next to each other. Each cell has a prisoner in it, and each cell is locked.

One night, the jailer gets bored and decides to play a game. For round 1 of the game, he takes a drink of whiskey,and then runs down the hall unlocking each cell. For round 2, he takes a drink of whiskey, and then runs down the

hall locking every other cell (cells 2, 4, 6, ?). For round 3, he takes a drink of whiskey, and then runs down the hall. He visits every third cell (cells 3, 6, 9, ?). If the cell is locked, he unlocks it; if it is unlocked, he locks it. He

repeats this for n rounds, takes a final drink, and passes out.

Some number of prisoners, possibly zero, realizes that their cells are unlocked and the jailer is incapacitated. They immediately escape.

Given the number of cells, determine how many prisoners escape jail.

Input

The first line of input contains a single positive integer. This is the number of lines that follow. Each of the following lines contains a single integer between 5 and 100, inclusive, which is the number of cells n.

Output

For each line, you must print out the number of prisoners that escape when the prison has n cells.

Sample Input

2

5

100

Sample Output

2

10

(1)编程思路。

本题与例17本质上是同类型的题,只是最终输出不一样。按例17的两种思路可以编写源程序1和2如下。

(2)源程序1。

#include <stdio.h>

int main()

{

int t,n,i,j,cnt,a[101]={0};

scanf("%d",&t);

for (i=1;i<=100;i++)

for (j=i;j<=100;j+=i)

a[j]=1-a[j];

while (t--)

{

scanf("%d",&n);

cnt=0;

for (i=1;i<=n;i++)

if (a[i]==1) cnt++;

printf("%d\n",cnt);

}

return 0;

}

(3)源程序2。

#include <stdio.h>

#include <math.h>

int main()

{

int t,n;

scanf("%d",&t);

while (t--)

{

scanf("%d",&n);

printf("%d\n",(int)sqrt(1.0*n));

}

return 0;

}

17-2  开灯

本题选自洛谷题库 (https://www.luogu.org/problem/P1876)

题目描述

首先所有的灯都是关的(注意是关!),编号为1的人走过来,把是1的倍数的灯全部打开;编号为2的人把是2的倍数的灯全部关上;编号为3的人又把是3的倍数的灯开的关上,关的开起来……直到第N个人为止。

给定N,求N轮之后,还有哪几盏是开着的。

输入格式

一个数N(1<=N<=2^40),表示灯的个数和操作的轮数。

输出格式

若干数,表示开着的电灯编号

输入样例

5

输出样例

1 4

(1)编程思路。

本题中N的值可能很大,因此采用例1中的思路1用数组模拟肯定会超时,因此只能采用思路2的做法。通过判断正整数i(1<=i<=N)是否为完全平方数,决定编号为i的灯是否是开着的。

(2)源程序。

#include <stdio.h>

int main()

{

long int i,n;

scanf("%ld",&n);

for (i=1;i*i<=n;i++)

printf("%ld ",i*i);

return 0;

}

17-3  又是开灯

本题选自洛谷题库 (https://www.luogu.org/problem/P1161)

题目描述

在一条无限长的路上,有一排无限长的路灯,编号为1,2,3,4,…。

每一盏灯只有两种可能的状态,开或者关。如果按一下某一盏灯的开关,那么这盏灯的状态将发生改变。如果原来是开,将变成关。如果原来是关,将变成开。

在刚开始的时候,所有的灯都是关的。小明每次可以进行如下的操作:

指定两个数,a,t(a为实数,t为正整数)。将编号为[a],[2×a],[3×a],…,[t×a]的灯的开关各按一次。其中[k]表示实数k的整数部分。

在小明进行了n次操作后,小明突然发现,这个时候只有一盏灯是开的,小明很想知道这盏灯的编号,可是这盏灯离小明太远了,小明看不清编号是多少。

幸好,小明还记得之前的n次操作。于是小明找到了你,你能帮他计算出这盏开着的灯的编号吗?

输入格式

第一行一个正整数n,表示n次操作。

接下来有n行,每行两个数a,t,其中a 是实数,小数点后一定有6位,t是正整数。

输出格式

仅一个正整数,那盏开着的灯的编号。

输入样例

3

1.618034  13

2.618034  7

1.000000  21

输出样例

20

说明/提示

数据保证,在经过n次操作后,有且只有一盏灯是开的,不必判错。

(1)编程思路。

本题如果采用例17的思路1进行模拟不是一种恰当的解法。首先题目中没有说明数据范围,只说“在一条无限长的路上,有一排无限长的路灯”,因此定义数组元素的个数需要斟酌;另外,n次操作,每次操作若干盏灯,模拟下来也可能会超时。因此,需要想出其他更简便的解决方法。

注意到题目的提示“在经过n次操作后,有且只有一盏灯是开的”。也就是说n次操作中除了一盏灯被按的次数是奇数次外,其余编号的灯被按的次数一定是偶数次。

以样例给出的数据为例:

第1次,“1.618034  13”,编号为1,3, 4, 6, 8, 9, 11, 12, 14, 16, 17, 19, 21这13盏灯的开关会被按一下;

第2次,“2.618034  7”,编号为2,5,7,10,13,15,18这7盏灯的开关会被按一下;

第3次,“1.000000  21”,编号为1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21这21盏灯的开关会被按一下。

可以看出除了编号20的灯外,其余编号均出现偶数次,即两两会成对出现。

异或运算有一个特性:数x与自身异或其值一定为0,而0和x异或结果为x。因此,将上面的表示灯的编号的41个数全部异或起来,结果一定是答案。因为根据题目的提示“在经过n次操作后,有且只有一盏灯是开的”可知,除一盏灯外,其余灯的编号一定两两出现,异或后一定为0。

(2)源程序。

#include <stdio.h>

int main()

{

int n,t,i,ans;

double a;

scanf("%d",&n);

ans=0;

while (n--)

{

scanf("%lf%d",&a,&t);

for (i=1;i<=t;i++)

ans=ans^((int)(a*i));

}

printf("%d\n",ans);

return 0;

}

C语言程序设计100例之(17):百灯判亮的更多相关文章

  1. 黑马程序员——经典C语言程序设计100例

    1.数字排列 2.奖金分配问题 3.已知条件求解整数 4.输入日期判断第几天 5.输入整数进行排序 6.用*号显示字母C的图案 7.显示特殊图案 8.打印九九口诀 9.输出国际象棋棋盘 10.打印楼梯 ...

  2. C语言程序设计100例之(4):水仙花数

    例4    水仙花数 题目描述 一个三位整数(100-999),若各位数的立方和等于该数自身,则称其为“水仙花数”(如:153=13+53+33),找出所有的这种数. 输入格式 没有输入 输出格式 若 ...

  3. C语言程序设计100例之(25):确定进制

    例25    确定进制 问题描述 6*9 = 42 对于十进制来说是错误的,但是对于13进制来说是正确的.即 6(13)* 9(13)= 42(13),因为,在十三进制中,42 = 4 * 13 + ...

  4. C语言程序设计100例之(22):插入排序

    例22  插入排序 问题描述 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素或记录的任意序列,重新排列成一个以关键字递增(或递减)排列的有序序列. 排序的方法有很多,简单插入排序就是一 ...

  5. C语言程序设计100例之(21):折半查找

    例21  折半查找 问题描述 顺序查找是一种最简单和最基本的检索方法.其基本思想是:从检索表的一端(如表中第一个记录或最后一个记录)开始,逐个进行记录的关键字和给定值的比较.若某个记录的关键字和给定值 ...

  6. C语言程序设计100例之(16):巧解算式

    例16  巧解算式 问题描述 在1.2.3.4.5.6.7.8.9.10个数中间加上加号或减号,使得到的表达式的值为自然数N,如果中间没有符号,则认为前后为一个数,如1 2 3认为是一百二十三(123 ...

  7. C语言程序设计100例之(15):除法算式

    例15   除法算式 问题描述 输入正整数n(2≤n≤68),按从小到大输出所有形如abcde/fghi=n的表达式.其中a~i为1~9的一个排列. 输入格式 每行为一个正整数n (n <= 1 ...

  8. C语言程序设计100例之(9):生理周期

    例9    生理周期 问题描述 人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为 23 天.28 天和33 天.每一个周期中有一天是高峰.在高峰这天,人会在相应的方面表现出色.例如 ...

  9. C语言程序设计100例之(6):数字反转

    例6    数字反转 题目描述 给定一个整数,请将该数各个位上数字反转得到一个新数.新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零(参见样例2). 输入格式 ...

随机推荐

  1. Redis 到底是怎么实现“附近的人”这个功能的?

    前言:针对“附近的人”这一位置服务领域的应用场景,常见的可使用PG.MySQL和MongoDB等多种DB的空间索引进行实现.而Redis另辟蹊径,结合其有序队列zset以及geohash编码,实现了空 ...

  2. 近万字案例:Rancher + VMware PKS实现全球数百站点K8S集群管理

    Sovereign Systems是一家成立于2007年的技术咨询公司,帮助客户将传统数据中心技术和应用程序转换为更高效的.基于云的技术平台,以更好地应对业务挑战.曾连续3年提名CRN,并且在2012 ...

  3. ESP8266开发之旅 网络篇④ Station——ESP8266WiFiSTA库的使用

    1. 前言     在前面的篇章中,博主给大家讲解了ESP8266的软硬件配置以及基本功能使用,目的就是想让大家有个初步认识.并且,博主一直重点强调 ESP8266 WiFi模块有三种工作模式: St ...

  4. ESP8266开发之旅 网络篇⑪ WebServer——ESP8266WebServer库的使用

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  5. e.target与事件委托简例(原生和jQuery的区别)

    target定义(英译:目标,目的): target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素.文档或窗口. 语法: event.target event.target.no ...

  6. electron开发环境搭建

    开发环境 Node.js Vscode vscode安装Debugger for Chrome 创建开发目录(也是解决方案) 执行初始化命令,创建electronpicture工程,并添加main.j ...

  7. Java 根据权重获取数据 基础 极简 准确率高

    package sl; import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.ut ...

  8. Html.CSS.JavaScript 学习经验

    HTML里面 不要使用 document.getElementsByName() 来获取 元素,会出错. 使用 document.getElementById()更好一些. substring()首字 ...

  9. OptimalSolution(2)--二叉树问题(2)BST、BBT、BSBT

    一.判断二叉树是否为平衡二叉树(时间复杂度O(N)) 平衡二叉树就是:要么是一棵空树,要么任何一个节点的左右子树高度差的绝对值不超过1. 解法:整个过程为二叉树的后序遍历.对任何一个节点node来说, ...

  10. 微信授权就是这个原理,Spring Cloud OAuth2 授权码模式

    上一篇文章Spring Cloud OAuth2 实现单点登录介绍了使用 password 模式进行身份认证和单点登录.本篇介绍 Spring Cloud OAuth2 的另外一种授权模式-授权码模式 ...