例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. openssl之aes对称加密

    AES:密码学中的高级加密标准(Advanced Encryption Standard,AES),又称 Rijndael加密法. 对称加密:用同一个密码  加密/解密  文件. 使用openssl中 ...

  2. windows下cmd组合命令和管道命令

    组合命令:&& 管道命令:|

  3. 百万年薪python之路 -- 运算符及while的练习

    1.判断下列逻辑语句的结果,一定要自己先分析 1)1 > 1 or 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6 1 &g ...

  4. Leetcode(7)整数反转

    Leetcode(6)Z字形变换 [题目表述]: 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 第一次:转字符串处理 执行用时:40 ms: 内存消耗:11.6MB 效果: ...

  5. 哈夫曼树C++实现详解

    哈夫曼树的介绍 Huffman Tree,中文名是哈夫曼树或霍夫曼树,它是最优二叉树. 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树. 这个定 ...

  6. Java基础(二十八)Java IO(5)RandomAccessFile类与过滤器流(Filter Stream)

    一.RandomAccessFile类 使用RandomAccessFile类可以读取任意位置数据的文件. 1.构造方法 RandomAccessFile(String name, String mo ...

  7. Redis(二)数据结构与键管理

    一.基础知识 1.全局命令 keys *   :查看所有键 dbsize:返回当前数据库中键的总数 exists key:检查键是否存在 del key ... :删除键 expire key sec ...

  8. Andriod一段时间未操作页面,系统自动登出

    功能描述: APP在公共的设备上运行,出于安全考虑,当登录的用户在超过一定时间内没有做任何操作, 则系统自动登出,用户如需重新操作APP,则需要重新登录 . 第一步:创建一个BaseActivity ...

  9. SpringBoot整合Logback

    本文主要讲与Boot整合,后面会详细讲解Logback 官方文档 ConsoleAppender 如 name 所示,附加在 console 上,或者更准确地说是 System.out 或 Syste ...

  10. 2018.8.10 python中的迭代器

    主要内容: 1.函数名的使用 2.闭包 3.迭代器 一.函数名的运用 函数名是一个变量,但他是一个特殊的变量,与括号配合可执行函数的变量. 1.函数名的内存地址 def func(): print(' ...