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

来源:https://www.cnblogs.com/cs-whut/archive/2019/11/23/11919420.html
-Advertisement-
Play Games

例17 百燈判亮 問題描述 有序號為1、2、3、…、99、100的100盞燈從左至右排成一橫行,且每盞燈各由一個拉線開關控制著,最初它們全呈關閉狀態。有100個小朋友,第1位走過來把凡是序號為1的倍數的電燈開關拉一下;接著第2位小朋友走過來,把凡是序號為2的倍數的電燈開關拉一下;第3位小朋友走過來, ...


例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;

}


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Spring Cloud Stream 是一個構建消息驅動微服務的框架,該框架在Spring Boot的基礎上整合了Spring Integrationg來連接消息代理中間件(RabbitMQ, Kafka等),提供了個性化的自動化配置實現,並引入了發佈-訂閱、消費組、分區這三個核心概念。 應用程... ...
  • 這是我以前解決問題時,收集在印象筆記里的內容,為了以後整理方便,把它轉移至這裡。以下內容,均來自微軟官方網站相關。 問題:C++控制台閃回 解決辦法: 1,在程式結尾添加system("pause");[若有return語句則寫在return之前] 解析:system(const char *com ...
  • 有序化 以小說章節目錄的數字為文件名,一章一個文件(但上千章就得有上千個文件) 在每次獲取小說章節里的內容時,給item添加新的標識,添加對應的章節的數字,全部存入資料庫,然後根據這個數字標識排序取出數據即可 去空行 利用splitlines()和strip() str.splitlines([ke ...
  • 題目:無重覆字元的最長子串。 給定一個字元串,請你找出其中不含有重覆字元的 最長子串 的長度。 示例 1: 輸入: “abcabcbb” 輸出: 3 解釋: 因為無重覆字元的最長子串是 “abc”,所以其長度為 3。 示例 2: 輸入: “bbbbb” 輸出: 1 解釋: 因為無重覆字元的最長子串是 ...
  • 數據的排序是在解決實際問題時經常用到的步驟,也是數據結構的考點之一,下麵介紹10種經典的排序方法。 首先,排序方法可以大體分為插入排序、選擇排序、交換排序、歸併排序和桶排序四大類,其中,插入排序又分為直接插入排序、二分插入排序和希爾排序,選擇排序分為直接選擇排序和堆排序,交換排序分為冒泡排序和快速排 ...
  • 在Python函數中,傳遞的參數如果預設有一個為 列表(list),那麼就要註意了,此處有坑. 入坑 挖坑 預期結果 執行結果 出坑 當定義函數時,會保存函數中預設參數 list 的值,也就是列表 li=[]; 在每次調用的時候如果傳遞了新的列表,則使用傳遞的列表,沒有傳遞,使用定義函數時保存的預設 ...
  • 前言文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。 作者: Rocky0429 在學習 Python 的過程中,我為它的簡潔優雅而痴迷,但它又是如此的調皮,在提供了很多舒服的功能特性之外,又悄悄挖了很多帶有迷惑性的坑,令人防不勝防 ...
  • 這是209.11.23的博客 下麵進入正題 Opencv的內容 各位都是大佬 HSV的顏色表和計算方法就不用說了吧 #include <opencv2/opencv.hpp> #include<iostream> #include<string> using namespace cv; using ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...