-
证明过程参考编程之美2015资格赛题解
题目1 :2月19日
时间限制:2000ms单点时限:1000ms内存限制:256MB描述
给定两个日期,计算这两个日期之间有多少个2月29日(包括起始日期)。
只有闰年有2月29日,满足以下一个条件的年份为闰年:
1. 年份能被4整除但不能被100整除
2. 年份能被400整除
输入
第一行为一个整数T,表示数据组数。
之后每组数据包含两行。每一行格式为"month day, year",表示一个日期。month为{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November" , "December"}中的一个字符串。day与year为两个数字。
数据保证给定的日期合法且第一个日期早于或等于第二个日期。
输出
对于每组数据输出一行,形如"Case #X: Y"。X为数据组数,从1开始,Y为答案。
数据范围
1 ≤ T ≤ 550
小数据:
2000 ≤ year ≤ 3000
大数据:
2000 ≤ year ≤ 2×109
- 样例输入
-
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
- 样例输出
-
Case #1: 1 Case #2: 0 Case #3: 1 Case #4: 3
1 #include <iostream> 2 #include <vector> 3 #include <string> 4 #include <algorithm> 5 using namespace std; 6 7 8 string MONTHS[12]={"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November" , "December"}; 9 10 int getMonth(string mon){ 11 for(int i = 0; i < 12; ++ i){ 12 if(mon == MONTHS[i]) return i+1; 13 } 14 return 0; 15 } 16 17 bool judgeLeapYear(int year){ 18 if( (year%4 == 0) && (year%100!=0) || (year%400 == 0)) return true; 19 else return false; 20 21 } 22 23 int main(){ 24 int T; 25 cin >> T; 26 string dot; 27 for( int icase = 1; icase <= T; ++ icase ){ 28 string monthStr; 29 int startDay,startYear; 30 cin >>monthStr>>startDay>>dot>>startYear; 31 int startMonth = getMonth(monthStr); 32 int endDay,endYear; 33 cin >> monthStr >> endDay >> dot>>endYear; 34 int endMonth = getMonth(monthStr); 35 int result= 0; 36 for(int i = startYear+1; i <= endYear-1; ++ i){ 37 if(judgeLeapYear(i)) result++; 38 } 39 if(startYear==endYear){ 40 if(judgeLeapYear(startYear) && startMonth <=2 && (endMonth >= 3 || (endMonth == 2 && endDay == 29))) result++; 41 }else{ 42 if(judgeLeapYear(startYear) && startMonth <= 2) result++; 43 if(judgeLeapYear(endYear) && (endMonth >= 3 || (endMonth == 2 && endDay == 29))) result++; 44 } 45 cout<<"Case #"<<icase<<": "<<result<<endl; 46 } 47 48 }
题目2 : 回文字符序列
时间限制:2000ms单点时限:1000ms内存限制:256MB描述
给定字符串,求它的回文子序列个数。回文子序列反转字符顺序后仍然与原序列相同。例如字符串aba中,回文子序列为"a", "a", "aa", "b", "aba",共5个。内容相同位置不同的子序列算不同的子序列。
输入
第一行一个整数T,表示数据组数。之后是T组数据,每组数据为一行字符串。
输出
对于每组数据输出一行,格式为"Case #X: Y",X代表数据编号(从1开始),Y为答案。答案对100007取模。
数据范围
1 ≤ T ≤ 30
小数据
字符串长度 ≤ 25
大数据
字符串长度 ≤ 1000
- 样例输入
-
5 aba abcbaddabcba 12111112351121 ccccccc fdadfa
- 样例输出
-
Case #1: 5 Case #2: 277 Case #3: 1333 Case #4: 127 Case #5: 17
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <cstdlib> 6 #include <cstring> 7 #include <cstdio> 8 9 #define MOD 100007 10 11 using namespace std; 12 13 int main(){ 14 int T; 15 cin >> T; 16 for(int icase = 1; icase <= T; ++ icase){ 17 string str; 18 cin >> str; 19 int dp[1005][1005]={0}; 20 memset(dp,0,sizeof(dp)); 21 for(int i = 0 ; i < str.length(); ++ i) dp[i][i] = 1; 22 for(int i = 1; i < str.length(); ++ i){ 23 for(int j = i-1; j >=0; -- j){ 24 dp[j][i]=(dp[j+1][i]+dp[j][i-1]-dp[j+1][i-1]+MOD)%MOD; 25 if(str[i]==str[j]) 26 dp[j][i]=(dp[j][i]+dp[j+1][i-1]+1+MOD)%MOD; 27 } 28 } 29 cout<<"Case #"<<icase<<": "<<dp[0][str.length()-1]<<endl; 30 } 31 32 }
题目3 : 基站选址
时间限制:2000ms单点时限:1000ms内存限制:256MB描述
需要在一个N × M的网格中建立一个通讯基站,通讯基站仅必须建立在格点上。
网格中有A个用户,每个用户的通讯代价是用户到基站欧几里得距离的平方。
网格中还有B个通讯公司,维护基站的代价是基站到最近的一个通讯公司的路程(路程定义为曼哈顿距离)。
在网格中建立基站的总代价是用户通讯代价的总和加上维护基站的代价,最小总代价。
输入
第一行为一个整数T,表示数据组数。
每组数据第一行为四个整数:N, M, A, B。
接下来的A+B行每行两个整数x, y,代表一个坐标,前A行表示各用户的坐标,后B行表示各通讯公司的坐标。
输出
对于每组数据输出一行"Case #X: Y",X代表数据编号(从1开始),Y代表所求最小代价。
数据范围
1 ≤ T ≤ 20
1 ≤ x ≤ N
1 ≤ y ≤ M
1 ≤ B ≤ 100
小数据
1 ≤ N, M ≤ 100
1 ≤ A ≤ 100
大数据
1 ≤ N, M ≤ 107
1 ≤ A ≤ 1000
- 样例输入
-
2 3 3 4 1 1 2 2 1 2 3 3 2 2 2 4 4 4 2 1 2 2 4 3 1 4 3 1 4 1 3
- 样例输出
-
Case #1: 4 Case #2: 13