8.20號考試總結

非气盈门發表於2024-08-20

1.考點

時間

1.閏年判斷

2.年,月,日判斷是否合法

3.迴文字串判斷

4.年,月,日,小時,秒的進位

2.考試成績

題目: T1 T2 T3 T4 T5 T6 總分
分數: 100 100 36 10 0 0 246
難度: 入門 入門 普及- 普及/提高- 普及- 普及/提高-

3.錯誤點

T3.[藍橋杯 2017 省 B] 日期問題:寫了暴力程式碼,但是沒法補零和if判斷太多,導致最後自己也不知道哪裡出現了BUG

T4.[藍橋杯 2020 省 AB2] 迴文日期:只對了一個測試點,純屬運氣。因為解法有問題,而且只判斷了前半部分,導致後半部分是否迴文無法判斷

T5.小挖的時間/T6.2038年問題:由於當時正在改T3和T4的程式碼部分,導致最後沒有時間思考這兩道題目,所以cout樣例就直接交上去了

4.改題

T3.[藍橋杯 2017 省 B] 日期問題

題目注意點:

1.不要暴力,用for迴圈一個一個迴圈出來年,月,日,時間十分充足

2.檢測迴圈出來的時間能否對的上要寫一個函式,否則十分混亂

3.要補零的地方要補零

4.判斷時要把四位數字的年份變成兩位數字,因為輸入時就是兩位

補題後程式碼

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 2;
const int N1 = 1e3 + 2;
typedef long long ll;
typedef unsigned long long ull;
//#define int long long
//#define fo(i,n,m) for(int i=n;i<=m;i++)
int mouth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31},a,b,c;
bool check(int x)//閏年判斷板子
{
	if((x%400==0)||(x%4==0&&x%100!=0))
	{
		return 1;
	}
	return 0;
}
bool ct(int x,int y,int z) //用ct函式判斷是否為輸入的數字
{
	if(a==x&&b==y&&c==z)
	{
		return 1;
	}
	else if(c==x&&b==z&&a==y)
	{
		return 1;
	}
	else if(c==x&&b==y&&a==z)
	{
		return 1;
	}
	return 0;
}
signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	char chuhao;
	cin>>a>>chuhao>>b>>chuhao>>c;
	for(int i=1960;i<=2059;i++)
	{
		if(check(i))//判斷閏年
		{
			mouth[2]=29;
		}
		else
		{
			mouth[2]=28;
		}
		for(int j=1;j<=12;j++)
		{
			for(int k=1;k<=mouth[j];k++)
			{
				int nian=i/10%10*10+i%10;//要算出來這裡的年份,因為輸入時的年份只有兩位
				if(ct(nian,j,k))
				{
					cout<<i<<'-'<<setw(2)<<setfill('0')<<j<<'-'<<setw(2)<<setfill('0')<<k<<'\n'; //如果只有一位數要補零
				}
			}
		}
	}
	return 0;
}

T4.[藍橋杯 2020 省 AB2] 迴文日期

題目注意點

1.從一天一天來算,一秒一秒來算回超時

2.判斷ABABBABA結構和迴文結構要各寫一個函式,而且只能儲存第一個迴文日期,所以還要打上標記

3.隨時都要判斷是否可以進位

補題後程式碼

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 2;
const int N1 = 1e3 + 2;
typedef long long ll;
typedef unsigned long long ull;
//#define int long long
//#define fo(i,n,m) for(int i=n;i<=m;i++)
int mouth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool check(int x)//閏年判斷板子
{
	if((x%400==0)||(x%4==0&&x%100!=0))
	{
		return 1;
	}
	return 0;
}
bool ct(string a)//判斷是否迴文
{
	string ans="";
	int len=a.length();
	for(int i=0;i<len;i++)
	{
		ans=a[i]+ans;
	}
	return ans==a;
}
bool huiwen(string a)//判斷是否為ABABBABA結構
{
	bool f1=(a[0]==a[2])&&(a[5]==a[7])&&(a[2]==a[5]);
	bool f2=(a[1]==a[3])&&(a[4]==a[6])&&(a[1]==a[4]);
	return f1&&f2;
}
signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin>>n;
    //算出年月日
	int y=n/10000;
	int m=n%10000/100;
	int d=n%100;
	bool flag1=0,flag2=0;//要打標記
	string ans1,ans2;
	while(1)//因為不知道什麼時候能找到,於是直接寫死迴圈
	{
		d++;
		if(check(y))//判斷是否為閏年
		{
			mouth[2]=29;
		}
        else
		{
			mouth[2]=28;
		}
        //進位
		if(d>mouth[m])
		{
			d=1;
			m++;
			if(m>12)
			{
				y++;
				m=1;
			}
		}
        //為了輸出,於是用string存起來
		string x=to_string(y*10000+m*100+d);
		if(!flag1&&ct(x))//如果迴文
		{
			ans1=x;//儲存答案
			flag1=1;//打上標記,避免下次繼續
		}
		if(!flag2&&huiwen(x))//如果是ABABBABA結構
		{
			ans2=x;//儲存答案
			flag2=1;//打上標記,避免下次繼續
		}
		if(flag1&&flag2)//假如說都被找到了
		{
			break;//迴圈退出
		}
	}
	cout<<ans1<<'\n'<<ans2;//輸出
	return 0;
}

T5.小挖的時間

題目注意點:

1.只有12個時間點,可以先除以\(60\*12=720\),這樣子可以省時間,否則就會TLE。

2.這裡的check函式要把個十百千都找出來,然後打三個tmp來算減去的時間

3.%720之前要把t/720*31給存進變數裡

補題後程式碼

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 2;
const int N1 = 1e3 + 2;
typedef long long ll;
typedef unsigned long long ull;
//#define int long long
//#define fo(i,n,m) for(int i=n;i<=m;i++)
bool check(int h,int m)
{
    //求出個十百千
	int g=m%10;
	int s=m/10;
	int b=h%10;
	int q=h/10;
	int tmp1=g-s,tmp2=s-b,tmp3=b-q;//求出差,看眼是否符合等差數列
	if(q==0)//如果小時只有個位數,那隻能特判
	{
		if(tmp1==tmp2)
		{
			return 1;
		}
		return 0;
	}
	if(tmp1==tmp2&&tmp2==tmp3)//如果符合等差數列
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int T,t;
	cin>>T;
	while(T--)
	{
		cin>>t;
		int h=12,m=0,cnt=t/720*31;//要先存在模
		t%=720;
		for(int i=1;i<=t;i++)
		{
			m++;
            //處理進位
			if(m==60)
			{
				h++;
				m=0;
			}
			if(h==13)
			{
				h=1;
			}
            //判斷這兩個時間符不符合等差數列
			if(check(h,m))
			{
				++cnt;
			}
		}
		cout<<cnt<<'\n';//由於T組資料點,於是要在迴圈內輸出
	} 
	return 0;
}

T6.2038年問題

題目注意點:

1.要開long long否則會爆int

2.閏年要每個迴圈都判

3.要進位時隨時都要進位

程式碼

#include <bits/stdc++.h>
using namespace std;
#define ll long long

int mouth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool check(int x) {//閏年判斷板子
	if ((x % 400 == 0) || (x % 4 == 0 && x % 100 != 0)) {
		return 1;
	}
	return 0;
}
ll t, n, year, month, day, h, m, s;
int main() {
	int T;//T組資料
	cin >> T;
	while (T--) {
		t = 1;
		cin >> n >> year >> month >> day >> h >> m >> s;
		for (int i = 1; i < n; i++) {
			t *= 2;		//每次都需要乘2
		}
		t--;//減去第一次的1
        //進位
		s += t;
		m += s / 60;
		s %= 60;
		h += m / 60;
		m %= 60;
		day += h / 24;
		h %= 24;
        //閏年
		if (check(year)) {
			mouth[2] = 29;
		} else {
			mouth[2] = 28;
		}
		while (day > mouth[month]) {	//如果時間大於月份時間
			day = day - mouth[month];
			month++;
            //進位
			if (month == 13) {
				month = 1;
				year++;
				if (check(year)) {//進位後要及時判閏年
					mouth[2] = 29;
				} else {
					mouth[2] = 28;
				}
			}
		}
		cout << year << " " << month << " " << day << " " << h << " " << m
		     << " " << s << endl;//輸出
	}
	return 0;
}

5.總結

不要一直寫暴力,要思考怎麼才能減時間。

考試時自己多想幾組HACK資料。

相關文章