C語言程序設計100例之(17):百燈判亮

例17   百燈判亮

問題描述編程

有序號爲一、二、三、…、9九、100的100盞燈從左至右排成一橫行,且每盞燈各由一個拉線開關控制着,最初它們全呈關閉狀態。有100個小朋友,第1位走過來把凡是序號爲1的倍數的電燈開關拉一下;接着第2位小朋友走過來,把凡是序號爲2的倍數的電燈開關拉一下;第3位小朋友走過來,把凡是序號爲3的倍數的電燈開關拉一下;如此下去,直到第100個小朋友把序號爲100的電燈開關拉一下。問這樣作過一遍以後,哪些序號的電燈是亮着的?數組

輸入格式ide

每行測試數據是一個正整數n,表明第n盞燈。測試

輸出格式this

每行輸出第n盞燈的狀態,0表明燈是熄滅的,1表明燈是亮的。spa

輸入樣例ip

1ci

5get

輸出樣例input

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盞燈,會由編號分別爲一、二、三、四、六、八、十二、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;

}

相關文章
相關標籤/搜索