2020年6月8日 星期一

a468: 12439 - February 29 解題心得

題目來源:https://zerojudge.tw/ShowProblem?problemid=a468

這題也是2012年大學程式檢定CPE的考題。

今年 2012 年,閏年。所以今年有「二月29日」,這天稱為「閏日」。有趣的是,今年二月29日出生的嬰兒要等到下一個閏年,也就是 2016 年才過生日。閏年是每 4 年一次嗎?能被 4 整除的年份是閏年,但是能被 100 整除的年份卻不是閏年,除非它可以被 400 整除。能被 400 整除的年份則是閏年。
本題給你兩個日期,你要找出它們兩者之間有幾個「閏日」。

輸入說明
第一行有一個 T (≤ 500) 表示測資筆數。

每筆測資兩行。第一行為第一個日期,第二行則為第二個。注意,第二個日期決不會比第一個早。所給的日期格式為  - 「月 日, 年」。詳細情形請參見範例輸出。所有日期均為正確日期,年份則介於 2 * 103 和 2 * 109 之間。月份名稱及每個月的天數詳列如下以便參考。

輸出說明
對於每筆測資,印出測資編號及兩個日期之間 (含) 有幾個「閏日」。


範例輸入 #1
4
January 12, 2012
March 19, 2012
August 12, 2899
August 12, 2901
August 12, 2000
August 12, 2005
February 29, 2004
February 29, 2012

範例輸出 #1
Case 1: 1
Case 2: 0
Case 3: 1
Case 4: 3
月份的名稱為 {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November" 及 "December"}. 平年中每個月的天數則依序是 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 及 31}。閏年時,二月有 29 天,其他月份則與平年相同。



如果你乍看這題會感到不知道從何下手,我建議你習慣性的在大腦中或是紙筆上寫下流程圖。

step0.請先別管幾月幾號,請先別管幾月幾號,請先別管幾月幾號

step1.跟隨題目定義出判斷閏年的條件

if(n % 400  && (n % 4 == 0 && n % 100 != 0)) {

    cout << n << "是閏年";

    }

step2.根據日期調整起始與終點區間

step3.求解。一班人在這個時候會先採用FORLOOP來比對區間內的每一年是不是閏年,但這題的側資不允許你這麼做,一定會超時,所以你必須簡化流程。

小時候我們都做過數學題:10以內可以被2整除但不能被6整除的數有幾個?

1 2 3 4 5 6 7 8 9 10

先用肉眼看,恩有4個,算式怎麼列呢==>10 / 2 - 10 / 6 = 4,有感覺了嗎,下面附上此題程式碼。





#include <iostream>

#include <algorithm>

#include <string>

#include <vector>

#include <map>

using namespace std;

int main()

{

int n, y , y1;

string m , d;

cin >> n;

int testCount = 0;

while (n-- > 0) {

testCount++;

cin >> m >> d >> y;

int count = 0;

if (m != "January" && m != "February") {

y++;

}

y--;

cin >> m >> d >> y1;

if ((m == "January") || (m == "February" && d != "29,")) y1--;

count = y1 / 4 - y1 / 100 + y1 / 400 - (y / 4 - y / 100 + y / 400);



cout << "Case " << testCount << ": " << count <<endl;

}



}

2020年6月4日 星期四

e948: 1. 基礎代謝率 (BMR Calculation) 解題心得

題目:https://toi-reg.csie.ntnu.edu.tw/question/201903/B1-BMR(Q).pdf

每逢過年總是年菜滿漢全席、打牌零嘴永遠吃不完,每天都坐著一直吃,體重一去不復返。為了保持苗條的身材,因此要來計算每天的基礎代謝率,看每天能吃多少零嘴。基礎代謝率(BMR)是指:在身體保持靜態下消耗的最低熱量(單位:大卡)。美國運動醫學協會提供了一個公式:

BMR(男) = (13.7×體重(kg)) + (5.0×身高(cm)) - (6.8×年齡) + 66。

BMR(女) = (9.6×體重(kg)) + (1.8×身高(cm)) - (4.7×年齡) + 655。

輸入說明
第一行有一個正整數 N (1 <= N <= 20),代表要計算 BMR 的人數。接下來 i 行 (i = 1, 2, …, N),每行各有四個正整數 G、A、H、W,彼此間以空白隔開。正整 數 G:1 (男)或 0 (女),代表計算者的性別;三個正整數 A (1 <= A<= 150)、H (1 <= H <= 250)、W (1 <= W <= 300):代表計算者的年齡、身高(cm)、體重(kg)。

輸出說明
對於每筆測資輸出一個浮點數,代表該人的基礎代謝率。BMR 四捨五入至 小數點後兩位,印完一人後換行。
範例輸入 #1    範例輸出 #1
2                        
1 10 100 20        772.00
0 20 120 30        1065.00

772.00
1065.00

範例輸入 #2         範例輸出 #2         
5                            
1 55 178 89            1801.30
0 20 157 48            1304.40
1 33 162 50            1336.60
1 10 150 31            1172.70
0 29 159 51            1294.50

解題心得:
其實這題已經把從輸入到輸出的計算公式都寫得清清楚楚,唯一的挑戰點就是怎麼輸出四捨五入至小數點後兩位。

cout中就有一個控制小數位數的函數(setprecision)(「setprecision」包含在<iomanip>函式庫內)。

cout  <<  setprecision(2)  << 4.123  <<  endl;
其中(2)代表輸出的位數,所以輸出會等於4.1

那如果只是想「控制小數點的位數」呢?
很簡單,只要加上「fixed」就可以囉,

cout  << fixed  <<  setprecision(2) << 10.2514<<  endl;
這時候(2)因為前面加上fixed,所以就代表輸出小數點後兩位,也就是10.25。

附上程式碼:
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
int main()
{
	double n, g, a, h, w;
	cin >> n;
	cout << fixed << setprecision(2);
	while (n-- > 0) {
		cin >> g >> a >> h >> w;
		if (g == 1) {
			cout << w * 13.7 + h * 5 - a * 6.8 + 66 << endl;
		}
		else {
			cout << w * 9.6 + h * 1.8 - a * 4.7 + 655 << endl;
		}
	}
}

UVa11286-Conformity 解題心得

     
Waterloo大學的新鮮人由於興趣不同,對於課程的選擇不盡相同,而校方希望他們所選的課程盡量一致,所以設立了一個獎項,頒發給 選擇的「課程組合」為「最受歡迎的課程組合」的學生。

      輸入有多組測試資料,每組資料的開頭有一個整數 n 表示新生的人數(1 <= n <= 10000),接下來有 n 列分別為這些新生所選擇的課程代號,每列有五個表示課程代號的整數,其值介於100~499。當 n = 0 表示測試資料結束。

      一組課程的受歡迎程度視所有剛好選擇該組課程的學生人數而定,如果沒有其他「課程組合」的人數比此「課程組合」的人數高,則該課程為最受歡迎的「課程組合」,請對每組測試資料輸出最受歡迎的「課程組合」的人數。

Sample Input
3
100 101 102 103 488
100 200 300 101 102
103 102 101 488 100
3
200 202 204 206 208
123 234 345 456 321
100 200 300 400 444
0
Output for Sample Input
2
3
==================================分割線========================================
這題有幾個需要注意的地方
1.重點是選課的組合!!選課的先後順序並不重要。先選100在選101跟先選101在選100是一樣的組合。

2.暴力法去掃每一個課程會超過限制的時間,所以這題的重點就在於運用map,PYTHON的話則是運用dict,這題則我用PYTHON解,所以用的是dict。

3.先將課程排序後如103 102 101 488 100變成100 101 102 103 488,再把100 101 102 103 488當成dict的KEY。

4.未來只要出現同樣一的一組課程,則dict[選課組合] += 1;

程式碼如下
def check():
while 1:
n = int(input())
if n == 0:
break;
b = {}
a = [[0 for i in range(5)] for j in range(n)]
ss = []
ss_a = ss.append
max = 0;
for i in range(n):
a[i] = input().split()
a[i].sort()
if(b.get(str(a[i])) == None):
ss_a((str(a[i])))
b[str(a[i])] = 1
else:
b[str(a[i])] += 1
if max < b[str(a[i])]:
max = b[str(a[i])]

sum = 0;
for i in ss:
if b[i] == max:
sum += max;
print(sum)


check()

3個孩子非學程式不可的理由



專家宣稱,未來世界可以分成三種人,一種人會寫程式,身為科技的創造者,在未來的世界裡,能完美融入各種領域,創造時代的脈動。另一種人是科技的駕馭者,身為科技的駕馭者自然不能跟程式完全脫鉤,也許不是一個高級專業的工程師,並然也是一個富含程式涵養與邏輯思維的科技人。最後一種人是程式的陌生人,不提能不能寫程式了,連基本的程式思維與邏輯訓練都不懂,在未來的世界裡,大量較低技術的勞力類型工作將被取代,這些人就是最危險的族群,脫離了程式,工作存續的風險絕對是與日俱增😱😱😱😱。
    
        從2019年最高薪的20個行業別來看,其中有5個行業跟電腦直接相關,其他15個行業也都在一定程度上依賴軟體工具來協助公司運作,但這都不是為什麼我認為從小就該學習程式的關鍵,我認為對於家長或是教育者來說,面對程式教育的心態才是學習的關鍵,以下分享我幾個觀點:
    
        1.程式設計非比一班科目,不能用傳統思維來看待,填鴨式教學,大量的功課、一昧地追求分數與證照都不是重中之重。反而邏輯思考的能力、解決問題的能力才是重點,跟大家分享一個親身案例,以前還在資訊業的時候,在我的部門裡,有許多師出名門甚至是海外歸國的資優生,他們領著不到我一半的薪水日以繼夜的加班完成不到我一半的工作量,我卻可以每天10點以後進辦公室,12點以後開始享用午休時光,下午開始玩線上遊戲,晚上準時打卡下班,這其中的重點就在於邏輯思考與解決問題的能力的差別,所以業界一昧在開的證照集訓班、密集加強班,都只是在用老舊的教育思維套用在新的教育類別上。
    
        2.不是每個人都得是工程師,所以重點是透過程式設計課程,學會專案分析、團隊合作的概念,未來的世界更仰賴的是人與人的團隊合作,正確的程式設計課程,會分為:分析、拆解、實作、測試(修正)四個步驟,分析的能力有助於孩子學會專案領導的能力,拆解有助於孩子在學習上將大問題或是將大目標拆解為許多小目標,這些都是可以完美融入孩子學習能力的培養,所以與其思考未來成不成為工程師這個太遠的問題,更應該開始思考的是怎麼讓孩子擁有跨領域的學習能力。
    
        3.程式設計越早學習越好,這門科目無關性別男女都適用,有時候你會發現,補再多習都不能讓孩子的成績有所提升,這時候你該思考的是孩子欠缺的不是解題的技巧與練習,而是解決問題的邏輯思維。

o079. 4. 最佳選擇

 題目描述: 給一個長度為 n 的正整數序列 a1,a2...an ,你可以執行多次操作 (包含 0 次),每次操作只能選擇這個序列的第一個或最後一個數字,再將這個數字從序列中刪除並自己搜集起來。 求滿足總和不超過 k 且搜集的數字奇數和偶數個數相同的條件下,所能搜集的數字總和最...