資訊學奧賽一本通 1109:開關燈 | OpenJudge NOI 1.5 31
阿新 • • 發佈:2021-01-20
技術標籤: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;
}