例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. jmeter-使用代理服务器录制脚本

    使用代理服务器录制脚本 1.测试计划-添加线程组 2.工作台添加HTTP代理服务器(路径:工作台-右键添加-非测试元件-HTTP代理服务器) 3.端口号一般由8888改为其他的 4.打开chrome的 ...

  2. prefer-object-spread

    eslint报错: Use an object spread instead of `Object.assign` eg: `{ ...foo }`.(prefer-object-spread) 即: ...

  3. C#初始类和命名空间

    本节内容: 1.剖析Hello,World程序 1.1初始类(class)与名称空间(namespace) 2.类库的引用 2.1DLL的引用(黑盒引用) 2.2项目引用(白盒引用) 2.3建立自己的 ...

  4. 玩转PubSubClient MQTT库

    1.前言     在ESP8266学习系列中,博主一直使用HTTP协议.HTTP连接属于短连接,而在物联网应用中,广泛应用的却是MQTT协议.所以,本篇我们将学习Arduino平台上的MQTT实现库 ...

  5. Web登录中的信心安全问题

    1. 一个简单的HTML例子看看用户信息安全 标准的HTML语法中,支持在form表单中使用<input></input>标签来创建一个HTTP提交的属性,现代的WEB登录中, ...

  6. 使用Apache common 的csv工具包处理csv文件

    1.向csv文件中追加数据 //向文件中追加数据 BufferedWriter csvBufferedWriter = new BufferedWriter(new OutputStreamWrite ...

  7. Apache 4.x HttpClient

    public static Map callRequest(String requestUrl, Method method, Map<String, String> data) thro ...

  8. 用Unity做游戏,你需要深入了解一下IL2CPP

    这次我们翻译了一篇Unity官方博客上的文章,原文题目为AN INTRODUCTION TO IL2CPP INTERNALS ,作者是从事Unity软件开发的Joshua Peterson.文章的看 ...

  9. C和C++中的引用传递

    两种引用传递的定义方式 第一种 #include<stdio.h> void changeValue(int *a); int main(){ int a =1; changeValue( ...

  10. reduce,map,filter 的用法

    # filter用法 (对每一个数据进行筛选,满足条件的就保留)# 1,filter(功能函数,容器类型数据)# 2,过滤出来是一个地址,用list,或tuple进行包装# 3,过滤出来的是原容器类型 ...