1.5211: 18歲
你到18歲需要過幾天,當然你的18歲生日還有可能不存在,比如你是今年2月29日出生的,那你每四年就只能過一個生日,18不是4的倍數,所以沒生日可過。
我們用變量sum表示我們到18歲的天數,接下來就只需要解決閏年還有平年的問題了,你是3月出生的,那今年閏年和你無關啊,你是二月前才有關聯,所以二月之后生日的你需要看的是下一年是不是閏年。也就是你的1歲生日不是因為你出生的那年是閏年就是366天,而是因為1.今年是閏年,而且你是3月前出生。2.明年是閏年,而且你是3月后(包含)出生
兩個數字之間的-可以用一個char字符讀入

#include <bits/stdc++.h> using namespace std; //判斷閏年函數 bool isLeapYear(int y) { if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) return true; return false; } int main() { int T; cin >> T; while (T--) { int y, m, d; char c; //讀入年月日,中間用char隔開 cin >> y >> c >> m >> c >> d; //總日子數sum int sum = 0; //2.29沒生日輸出 if (m == 2 && d == 29) { cout << "-1" << endl; continue; } //3月之后(包括)看下一年 if (m > 2) y++; //循環18年 for (int i = y; i < y + 18; i++) { if (isLeapYear(i)) sum += 366; else sum += 365; } cout << sum << endl; } return 0; }
2.1060: 鵲橋相會
這個題目看起來很復雜,但是需要自己不去關注那些無用的條件。因為喜鵲只能往一個方向飛,還想帶着牛郎往織女方向飛,天和是正方向,所以喜鵲的位置必須是負數或牛郎所在的位置0,喜鵲的速度必須是正數才飛對了方向。之后就是路程s是w*1000-t(因為t是負數,減去變正數),速度是v,時間t=s/v,取最小即可
你可以估算一下最大時間,就是w=1000,t=1000,v=1,也就是10001000,我只要設置一個大於他的數就可以作為最大值了

#include <bits/stdc++.h> using namespace std; int main() { int w, n; while (cin >> w >> n, w || n) { //設置一個到達不了時間,也就是最大時間+1 int minTime = 10001001; while (n--) { int t, v; cin >> t >> v; if (t <= 0 && v > 0) { //時間=路程/速度 int time = (w * 1000 - t) / v; if (time < minTime) { minTime = time; } } } if (minTime == 10001001) cout << "Can't Solve\n"; else cout << minTime << "\n"; } return 0; }
我們可以先計算出商品總額,之后先使用滿減優惠,再使用紅包,使用需要注意自己的優惠券夠不夠,當然超過了不能不能支付負數

#include <bits/stdc++.h> using namespace std; int main() { int T; cin >> T; while (T--) { int n, p, q, sum = 0; cin >> n >> p >> q; for (int i = 0,x; i < n; i++) { cin >> x; sum += x; } //discount優惠,表示滿減優惠金額 int dis = (sum / 400) * 50; //可滿減比擁有的少 if (p < dis) sum -= p; else sum -= dis; //使用紅包優惠,金額比紅包少 if (sum < q) sum = 0; else sum -= q; cout << sum << endl; } return 0; }
4.5857: 桃子的高低音
這個題目簡單描述,就是一個高音就是他比兩邊的都高,那么我只要用每個數比較就好了,第一個和最后一個不會是高音

#include <bits/stdc++.h> using namespace std; const int N=1e5+5; int a[N]; int main() { int t; cin >> t; while (t--) { int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; int num=0; //兩邊均比中間大,滿足統計 for (int i = 1; i < n - 1; i++) if (a[i] > a[i - 1] && a[i] > a[i + 1]) num++; cout << num << endl; } }
5.3016: 兩圓位置關系
兩圓的位置關系,和兩圓點距離有關,關系如下:
學好編程之前一定要學好數學,加油~
但是距離算出來是一個浮點數,直接比較可能會出問題,我們直接對其進行平方,這樣也不需要考慮誰大誰小了,不需要取絕對值了

#include <bits/stdc++.h> using namespace std; int main() { int x1, y1, r1; while (cin >> x1 >> y1 >> r1) { int x2, y2, r2; cin >> x2 >> y2 >> r2; int D = (r1 + r2) * (r1 + r2), d = (r1 - r2) * (r1 - r2); double len = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); int ans; //以下是if嵌套的,注意! if (D == len || d == len) { //兩圓心距離與半徑之和或之差相等 ans = 1; } else if (len > D) { //兩圓心距離大於半徑之和 ans = 2; } else if (len < d) { //兩圓心距離小於於半徑之差 ans = 3; } else { ans = 4; } cout << ans << endl; } return 0; }
6.5044: 在霍格沃茨找零錢
十七個銀西可(Sickle)兌一個加隆(Galleon),二十九個納特(Knut)兌一個西可。和時間是不是很像,1小時是60分,1分鍾是60秒。這都屬於進制轉換題目,我們先取余,再取整拋棄這一位就可以了

#include <bits/stdc++.h> using namespace std; int main() { int p[3], a[3]; char b; cin >> p[0] >> b >> p[1] >> b >> p[2] >> a[0] >> b >> a[1] >> b >> a[2]; //應付的總納特 int sum1 = p[0] * 17 * 29 + p[1] * 29 + p[2]; //實付的總納特 int sum2 = a[0] * 17 * 29 + a[1] * 29 + a[2]; int sum = sum2 - sum1, ans[3]; //錢沒帶夠先輸出負號 if (sum < 0) { cout << "-"; sum = -sum; } //獲取納特數 ans[2] = sum % 29; //丟去納特數 sum = sum / 29; //獲取銀西可數 ans[1] = sum % 17; //丟去銀西可數 sum = sum / 17; //sum即為加隆數 ans[0] = sum; cout << ans[0] << "." << ans[1] << "." << ans[2] << endl; }
7.4020: 有道水題
獲取每一位還是需要進制轉換。但是也可以直接用字符串來做這個題目,記得減去字符0

#include <bits/stdc++.h> using namespace std; int main() { int T; cin >> T; while (T--) { string s; cin >> s; int sum = 0; for (int i = 0; s[i]; i++) sum += s[i] - '0'; //sum1代表從第1位到這一位總和 //flag為0表示不存在 int sum1 = 0, flag = 0; for (int i = 0; s[i]; i++) { sum1 += s[i] - '0'; //直接除以2下取整會出問題 if (sum1 + sum1 == sum) { //存在結束循環 flag = 1; break; } } if (flag) cout << "YES\n"; else cout << "NO\n"; } }
8.5128: 就是要62
還是進制轉換,2進制轉10進制。11的二進制表示是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,也就是第i位要乘上2^(len-1)
獲取每一位的進制轉換我們是倒過來,這個我們可以正過來,保證*2的次數對就可以了

#include <bits/stdc++.h> using namespace std; int main() { string s; //讀入要進行轉換的字符串s cin >> s; //設置變量t去保存這個答案 int t = 0; for (int i = 0; s[i]; i++) { t = t * 2 + (s[i] - '0'); } cout << t << "\n"; }
之后我們要把十進制轉換為一位的一位,這樣會幫我們倒過來

#include <bits/stdc++.h> using namespace std; int main() { string s; //讀入要進行轉換的字符串s while (cin >> s) { //設置變量t去保存這個答案 int t = 0; for (int i = 0; s[i]; i++) { t = t * 2 + (s[i] - '0'); } int len = 0; //10^9就是1后面有9個0,是十位 int a[10]; while (t) { //存儲當前位 a[len++] = t % 10; //丟棄當前位 t /= 10; } int num = 0; for (int i = 1; i < len; i++) { //是26,字符串被倒過來了 if (a[i - 1] == 6 && a[i] == 2) num++; //是62 if (a[i - 1] == 2 && a[i] == 6) num++; } cout << num << "\n"; } }
9.1091: JudgeOnline
這個題目就是判斷字符,你可能會忘記了tab符'\t',因為要讀取空格,請整行讀入

#include <bits/stdc++.h> using namespace std; int main() { string s; //有空格,直接getline while (getline(cin, s)) { for (int i = 0; s[i]; i++) { if (s[i] == '<') cout << "<"; else if (s[i] == '>') cout << ">"; else if (s[i] == ' ') cout << " "; else if (s[i] == '\t') cout << "	"; else cout << s[i]; } cout << "\n"; } }
10.5858: 桃子的游戲
題意其實也蠻簡單的,就是三個人初始是x、y和z,之后每個時間+i,然后按照兩個條件進行加減點數,但是是一個三重循環
第一重循環是T組,第二重是q組,第三重是t的枚舉
記得使用long long,1e5+(1+1e4)/2*1e4超過了int

#include <bits/stdc++.h> using namespace std; int main() { int T; cin >> T; //有T組 while (T--) { int x, y, z; //讀入三個初始值 cin >> x >> y >> z; int q; cin >> q; while (q--) { int n; //讀入這次查詢的時間 cin >> n; //用X、Y和Z代表他們的當前值,但是這個值會超過int long long X = x, Y = y, Z = z; for (int i = 1; i <= n; i++) { //每個人都可以得到i點 X += i, Y += i, Z += i; if (Y >= 3) { //小明給桃子3點 Y -= 3; X += 3; } if (Z >= 6) { //小強給桃子6點 Z -= 6; X += 6; } } //最后是否比兩個人的大 if (X > Y && X > Z) cout << "Yes\n"; else cout << "No\n"; } } return 0; }
11.5265: 圍棋入門
如果這個棋子是白棋,那么他周圍這四個就有可能要被你輸出。所以去找到所有的白棋,看看其是否要輸出
還有一個事情很麻煩,就是邊界,我們不能越界,那我們可以將其第0行第0列空出來
行號從小到大的順序輸出,如果行號相同,則按照列號從小到大的順序,這個我們用一個數組去記錄我們的答案

#include <bits/stdc++.h> using namespace std; int ans[25][25]; char s[25][25]; //定義方向數組dir int dir[4][2]={1,0,-1,0,0,1,0,-1}; int main() { //讀入第一行,存儲從s[1][1]開始 while(cin>>(s[1]+1)) { int n=19; for(int i=2;i<=n;i++) { //讀入第i行,存儲從s[i][1]開始 cin>>(s[i]+1); } //清空答案 memset(ans,0,sizeof(ans)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { //枚舉每一個棋子,是W,需要找四個棋子 if(s[i][j]=='W') { for(int k=0;k<4;k++) { int x=i+dir[k][0]; int y=j+dir[k][1]; //是.代表可以放置 if(s[x][y]=='.')ans[x][y]=1; } } } } //假設白棋已經被圍住 int flag=1; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { //枚舉每一個坐標看是否需要輸出,這樣可以保證先行再列 if(ans[i][j]) { cout<<i<<" "<<j<<"\n"; flag=0; } } } if(flag)cout<<"YuYu Wins!\n"; } }
12.1437: Zigzag
是不是和蛇形矩陣有點像,但是這個題目需要自己去設計循環,是一樣的斜線,但是這個題還有方向,對角線可能是從左下到右上,也有可能是右上到左下
所以我們還需要借助一個變量去控制現在是哪個方向
flag=1代表左下到右上,也是一開始的方向,flag=-1代表從右上到左下,然后讓其循環
最后的右下角重新找規律輸出

#include <bits/stdc++.h> using namespace std; int main() { int n, a[25][25]; while (cin >> n ,n) { int s = 1, flag = 1; //對角線和為i for (int i = 0; i < n; i++) { //左下開始是0 for (int j = 0; j <= i; j++) { //左下到右上填充,否則顛倒填充 if (flag == 1) a[i - j][j] = s++; else a[j][i - j] = s++; } flag = -flag; } //右下角,最后是2n-2 for (int i = n; i < n + n-1; i++) { //左下開始是n-i for (int j = i-n+1; j < n; j++) { cout<<j<<" "<<i-j<<"\n"; if (flag == 1) a[i - j][j] = s++; else a[j][i - j] = s++; } flag = -flag; } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (j != 0) cout << " "; printf("%-3d", a[i][j]); } cout << endl; } cout<<"\n"; } return 0; }
13.1438: 螺旋形
這個題目就麻煩了,之前你們沒有見過,但是我們可以思考一下,每次我們都是四個操作,向右,向下,向左,向上,一圈一圈往里填。

#include <bits/stdc++.h> using namespace std; int main() { int n, a[25][25]; while (cin >> n, n) { //n是1沒有四個方向特判掉 if (n == 1) a[0][0] = 1; else { //i和j代表當前要填充的坐標,now是當前要填的數,N是最大可以填的數字 int i = 0,j = 0, now = 1, N = n * n; //設置四個上下左右變量,代表當前所在位置 int U = 0, D = n - 1, L = 0, R = n - 1; while (now <= N) { //向右走,列++ while (j < R && now <= N) { a[i][j] = now++; j++; } //向下走,行++ while (i < D && now <= N) { a[i][j] = now++; i++; } //向左走,列-- while (j > L && now <= N) { a[i][j] = now++; j--; } //向上走,行-- while (i > U && now <= N) { a[i][j] = now++; i--; } //縮一圈,i和j各加1 i++,j++; //縮一圈,U到了下一行,D到上一行,L到下一列,R到前一列 U++, D--, L++, R--; //填充最后一個數 if (now == N) a[i][j] = now++; } } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (j != 0) cout << " "; printf("%-3d", a[i][j]); } cout << endl; } cout << "\n"; } }
這篇博客還有兩種寫法,你需要推算出下標所對應的數字或者按照循環的方式去解答
14.3297: 名偵探柯南-破解死亡訊息
需要讀懂這個題目,拿到字符s[i]代表的是我們這一密碼段有s[i]-'A'個字符,這s[i]-'A'個字符要進一步解碼,變為數字求和

#include <bits/stdc++.h> using namespace std; int main() { string s; while (cin >> s) { for (int i = 0; s[i]; i++) { //sum為當點段解碼,c代表當前密碼段有幾個 int sum = 0, c = s[i] - 'A' + 1; for (int j = i; j < i + c; j++) sum = sum + s[j] - 'A' + 1; cout << sum; //下一次訪問i+c,因為還要執行i++,回退一個 i = i + c - 1; } cout << "\n"; } return 0; }
15.5168: 報時助手
一個比較復雜的模擬題,我們需要考慮各種情況,這個題目要先思考好在再動手
我只是提供一種代碼實現,你也可以自己想一個思路去避所有可能產生的bug,從而AC題目

#include <bits/stdc++.h> using namespace std; string s[25] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty"}; int main() { int m, n; cin >> m >> n; //m比20小,我們已經有了輸出答案 if (m <= 20) cout << s[m]; else { //將其拆成20+(m-20)進行輸出 cout << s[20] << " " << s[m - 20]; } //是整點直接輸出 if (n == 0) { cout << " o'clock"; } else if (n <= 20) { //小於20直接輸出 cout << " " << s[n]; } else if (n < 30) { //將其拆成20+(n-20)進行輸出 cout << " " << s[20] << " " << s[n - 20]; } else if (n < 40) { //將其拆成30+(n-30)進行輸出 cout << " thirty"; //n-30是0不能輸出 if (n - 30) cout << " " << s[n - 30]; } else if (n < 50) { //將其拆成40+(n-40)進行輸出 cout << " forty"; //n-40是0不能輸出 if (n - 40) cout << " " << s[n - 40]; } else { //將其拆成50+(n-50)進行輸出 cout << " fifty"; //n-50是0不能輸出 if (n - 50) cout << " " << s[n - 50]; } cout << "\n"; return 0; }
16.5136: 隧道有多長
這個題目也不難,就是你需要統計一個字符串中間有多少個連續的'#',當然也會不存在,所以最小值這個特別注意
我們可以一重循環去統計

#include <bits/stdc++.h> using namespace std; int main() { string s; while (cin >> s) { //用mi和mx來記錄答案,t來記錄當前的長度 int mi = 0, mx = 0, t = 0; for (int i = 0; s[i]; i++) { //是'#'需要將隧道長度+1 if (s[i] == '#')t++; //其他需要統計答案的情況 //1.不是隧道 2.最后一個字符了 if (s[i] == '*' || s[i + 1] == 0) { //最小值不是0取小 if (mi) { //t也不是0才能更新 if (t) mi = min(mi, t); } else mi = t; //最大值不是0,取大 if (mx) { mx = max(mx, t); } else mx = t; t = 0; } } cout << mi << " " << mx << endl; } return 0; }
17.3212: Pig在哪里
這個題目也很簡單,你需要判斷連續的三個字符是不是pig

#include <bits/stdc++.h> using namespace std; int main() { int T; cin >> T; while (T--) { int n; string s; cin>>n>>s; int num=0; //從可以訪問i-2開始 for(int i=2;i<s.length();i++) { if(s[i-2]=='p'&&s[i-1]=='i'&&s[i]=='g') num++; } cout<<num<<"\n"; } return 0; }
18.3134: 淵子賽馬修改版
課堂上貪心的一個擴展,這個題目還是有一定難度的,允許平局我就得考慮這把怎么要平局
1.最好的最差都可以,那就贏了2.淵子最好的馬比對手差,直接用下等馬輸掉3.相等,如果最差的馬太菜,輸掉,否則平局
代碼會比思想更直觀些

#include<bits/stdc++.h> using namespace std; int a[10005],b[10005]; int main() { int n; while(cin>>n,n) { for(int i=0; i<n; i++)cin>>a[i]; //淵子的馬從小到大排序 sort(a,a+n); for(int i=0; i<n; i++)cin>>b[i]; //對手的馬從小到大排序 sort(b,b+n); //aL(a數組左端點)是淵子當前最差的馬的下標 //aR(a數組右端點)是淵子當前最好的馬的下標 //bL是對手當前最差的馬的下標,aR是對手當前最好的馬下標 int aL=0,bL=0,aR=n-1,bR=n-1; //ans代表當前的凈勝場數 int ans=0; for(int i=0; i<n; i++) { if(a[aL]>b[bL]) { //淵子最差的馬比對手的還好,直接比掉 aL++,bL++,ans++; } else if(a[aR]>b[bR]) { //淵子最好的馬比對手的還好,也可以直接比掉 aR--,bR--,ans++; } else if(a[aR]<b[bR]) { //淵子最好的馬比對手差,直接用下等馬輸掉 aL++,bR--,ans--; } else if(a[aR]==b[bR]) { //最好的馬相等,那么我需要考慮一下 //淵子最差的馬比對手好的馬差了,算了,用差馬輸出了 if(a[aL]<b[bR])ans--; //如果相等呢,那就是淵子剩下的馬全一樣了,直接平局就行 //!!!這個平局很重要,沒有凈勝減少 aL++,bR--; } } //凈勝場數為正,為0,為負分別對應三種情況 if(ans>0) cout<<"Win\n"; else if(ans==0) cout<<"Draw\n"; else cout<<"Lost\n"; } return 0; }
19.5725: 營養膳食
貪心,按照脂肪指數從高到低排序,這種種類還可以選擇就選擇,且只能選m個。

#include <bits/stdc++.h> using namespace std; const int N = 1005; struct T { int ai, bi; } a[N]; int num[N]; bool cmp(T a, T b) { return a.ai > b.ai; } int main() { int n, m, k; cin >> n >> m >> k; for (int i = 1; i <= k; i++) cin >> num[i]; for (int i = 0; i < n; i++) cin >> a[i].ai >> a[i].bi; //按照ai進行排序,先吃脂肪指數高的 sort(a, a + n, cmp); int sum = 0; //進來選食物 for (int i = 0; i < n; i++) { //當前類別可選 if (num[a[i].bi]) { //把脂肪指數加上 sum = sum + a[i].ai; //這種種類的少一份 num[a[i].bi]--; m--; if (!m)break; } } cout << sum; return 0; }
20.3457: 最小新數
又回到了之前的進制轉換,你可以得到0~9出現的位數
這個題目也是貪心,你需要從小開始輸出,但是你不能直接先輸出0,一個數不能從0開始,所以你要先輸出一個。

#include <bits/stdc++.h> using namespace std; int main() { string s; while(cin>>s) { //看0~9的出現次數 int a[10]={0}; for(int i=0;s[i];i++) a[s[i]-'0']++; //先輸出一個非0最小數字 for(int i=1;i<10;i++) { if(a[i]>0) { cout<<i; a[i]--; break; } } //繼續從0開始,從小到大輸出 for(int i=0;i<10;i++) { while(a[i]) cout<<i,a[i]--; } cout<<endl; } return 0; }
21.6149: 因子個數排序

#include <bits/stdc++.h> using namespace std; int a[205]; //計算因子個數函數 int cal(int n) { //sqrt是浮點數,可能會有問題,+0.5不會出問題 int x = sqrt(n + 0.5); //因為你最多算到一半,算出來因子i,那么n/i也是 int s = 0; for (int i = 1; i <= x; i++) { if (n % i == 0) { //3*3=9,這種完全平方特殊處理下 if (i * i == n) s++; else s += 2; } } return s; } int cmp(int s, int t) { //分別計算兩數因子數 int s1 = cal(s), s2 = cal(t); //相等,比較兩個大小 if (s1 == s2) return s > t; return s1 > s2; } int main() { int n; while (cin >> n) { for (int i = 0; i < n; i++) cin >> a[i]; sort(a, a + n, cmp); for (int i = 0; i < n - 1; i++) cout << a[i] << " "; cout << a[n - 1] << "\n"; } return 0; }
22.3148: 按1的個數排序

#include<bits/stdc++.h> using namespace std; string s[100]; int cmp(string s,string t) { //分別找到兩個字符串1的個數 int s1=0,s2=0; for(int i=0;s[i];i++) if(s[i]=='1')s1++; for(int i=0;t[i];i++) if(t[i]=='1')s2++; //1的個數相等,按照s和t字典序排序 if(s1==s2)return s<t; return s1<s2; } int main() { int n; cin>>n; for(int i=0;i<n;i++) cin>>s[i]; sort(s,s+n,cmp); for(int i=0;i<n;i++) cout<<s[i]<<endl; return 0; }