1. 程式人生 > 其它 >資訊學奧賽一本通 1109:開關燈 | OpenJudge NOI 1.5 31

資訊學奧賽一本通 1109:開關燈 | OpenJudge NOI 1.5 31

技術標籤:C++基礎資訊學奧賽一本通題解OpenJudge NOI題解c++

【題目連結】

ybt 1109:開關燈
OpenJudge NOI 1.5 31:開關燈

【題目考點】

1. 模擬

2. 迴圈、陣列

3. 用逗號分隔輸出

設標誌位:isFirst,表示現在輸出的是否是第一個元素。

  • 如果現在要輸出第一個元素,不輸出逗號,將isFirst設為false。
  • 如果現在不輸出第一個元素,輸出逗號
//例:用逗號分隔輸出陣列a的n個元素
bool isFirst = true;
for(int i = 0; i < n; ++i)
{
	if(isFirst)
		isFirst = false
; else cout<<','; cout<<a[i]; }

【思路及題解程式碼】

解法1:用陣列模擬

  • 設陣列a,a[i]表示第i號燈是否亮
  • 模擬操作過程,第1個人改變1倍數的燈的狀態,第2個人改變2倍數的燈的狀態…直到第m個人操作完畢。
  • 遍歷陣列a,輸出關閉著的燈的編號。
#include <bits/stdc++.h>
using namespace std;
int main()
{
    bool a[5005] = {};//a[i]表示第i號燈是否亮。第1個人將燈全部關閉,因此將所有元素初始化為false。 
    int n, m;//n盞燈,m個人 
cin>>n>>m; for(int i = 2; i <= m; ++i)//i為人編號,從第2個人開始操作 { for(int j = 1; j <= n; ++j)//j為燈編號,遍歷所有的燈 { if (j % i == 0)//如果燈編號是人編號的倍數 { if(a[j])//或者這一段寫為:a[j] = a[j] ? false : true; a[j] = false; else
a[j] = true; } } } bool isFirst = true;//是否是第一個要輸出的數字 for(int j = 1; j <= n; ++j)//遍歷所有燈 { if(a[j] == false)//如果第j盞燈關著 { if (isFirst) isFirst = false; else cout<<','; cout<<j; } } return 0; }

解法2:不用陣列,考察每盞燈被操作的次數

  • 遍歷每個燈,設燈的編號為i,那麼只有編號為i的因數的人才會操作這盞燈。
    如:6號燈,會被編號為1,2,3的人操作,而這三個數是6的因數(6能整除的數字)。
  • 所有燈初始是亮著的。統計燈被操作的次數,如被操作奇數次,則最後燈是滅著的,那麼最後關閉著的燈的數量加1。如被操作偶數次,燈是亮著的。
  • 統計操作次數,操作次數是燈編號i與最大操作次數m中較小的值。
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n, m;
    cin>>n>>m;//n盞燈 m個人 
    cout<<1;//1號燈只被第一個人操作,一定是關閉的 
    for(int i = 2; i <= n; ++i)//燈i會被編號為"i的因數"的人操作 
    {
    	int c = 0;//計數,計該燈被操作多少次 
        for(int j = 1;j <= m && j <= i; ++j)//j:人編號。看j從1~m或i(m,i取較小的值),有幾個數是i的因數,那麼該燈就被操作多少次。 
        {
        	if(i % j == 0)
            	c++;
        }
        if(c % 2 == 1)//燈最初是亮著的,進行奇數次操作後,燈會滅 
        	cout<<','<<i;
    }
    return 0;
}