PTA团体程序设计天梯赛篇(一)----模拟专题
模擬專題
- 字符串模擬
- c++ 常用字符串處理函數
- 1. 截取子串
- 2. 替換子串
- 3. 查找子串
- 4、刪除字符串
- 5、判斷與轉換函數
- 6 翻了(替換子串)
- 敲笨鐘(字符串查找+字符串替換)
- 估值一億的AI核心代碼(替換+刪除+查找)
- 福到了 (字符串+翻轉)
- 數學模擬
- 特立獨行的幸福(模擬+map+素數)
- 多項式除法
- N個數求和
- 矩陣乘法
- 技巧模擬
- 天梯賽座位分配 (模擬 + 技巧)
- 倒數第N個字符串(數學知識 + 技巧)
- 秀恩愛分得快
- 其余
- 名人堂與代金券(技巧)
- 刮刮彩票
字符串模擬
c++ 常用字符串處理函數
1. 截取子串
s.substr(pos, n) 截取s中從pos開始(包括0)的n個字符的子串,并返回
s.substr(pos) 截取s中從從pos開始(包括0)到末尾的所有字符的子串,并返回
2. 替換子串
s.replace(pos, n, s1) 用s1替換s中從pos開始(包括0)的n個字符的子串
3. 查找子串
s.find(s1) 查找s中第一次出現s1的位置,并返回(包括0)s.find(s1 , p) 從位置p開始查找s中第一次出現s1的位置,并返回(包括0)s.rfind(s1) 查找s中最后次出現s1的位置,并返回(包括0)s.find_first_of(s1) 查找在s1中任意一個字符在s中第一次出現的位置,并返回(包括0)s.find_last_of(s1) 查找在s1中任意一個字符在s中最后一次出現的位置,并返回(包括0)s.fin_first_not_of(s1) 查找s中第一個不屬于s1中的字符的位置,并返回(包括0)s.fin_last_not_of(s1) 查找s中最后一個不屬于s1中的字符的位置,并返回(包括0)4、刪除字符串
iterator erase(iterator first, iterator last);//刪除[first,last)之間的所有字符,返回刪除后迭代器的位置
iterator erase(iterator it);//刪除it指向的字符,返回刪除后迭代器的位置
string &erase(int pos = 0, int n = npos);//刪除pos開始的n個字符,返回修改后的字符串
5、判斷與轉換函數
6 翻了(替換子串)
題目鏈接
解題思路:這題是練習使用replace函數的 , 當我們使用該函數替換后,由于原字符的一些片段被替換后,會導致字符串的長度發生變化,因此我們在使用好,切記要與變化后的長度進行相應變化。
代碼:
#include <iostream> #include <algorithm> #include <string> using namespace std;int main() {string s;getline(cin, s);int n = s.size();int p = 0;cout << n << endl;for (int i = 0 ; i < n ; ++i) {if (s[i] == '6') {p = i;int ss = 0;while (s[i] == '6')ss++, i++;cout << ss << " " << p << endl;if (ss > 3 && ss <= 9) {[添加鏈接描述](https://pintia.cn/problem-sets/994805046380707840/problems/1111914599412858880) s.replace(p, ss, "9");i = i - ss + 1; // 在替換之后字符串長度變換那么i對應的位置就需要變化} else if (ss > 9) {s.replace(p, ss, "27");i = i - ss + 2;}}n = s.size();}cout << s << endl;return 0;}敲笨鐘(字符串查找+字符串替換)
題目鏈接
解題思路:
代碼:
#include <iostream> #include <string> using namespace std;string s, ss = "qiao ben zhong."; int main() {int n ;cin >> n;getchar();while (n--) {getline(cin, s);int flag = 0;if (s.find("ong,") != string::npos)flag ++;if (s.find("ong.") != string::npos)flag ++;if (flag == 2) {int pos = s.size() - 1;while (pos--) {if (s[pos] == ' ')flag ++;if (flag == 5)break;}s.replace(pos + 1, s.size() - pos, ss );cout << s << endl;} elsecout << "Skipped\n" ;}return 0; }估值一億的AI核心代碼(替換+刪除+查找)
題目鏈接
解題思路:
這是一個綜合性非常強的題目了。對于刪除字符來說,我們要靈活運用:iterator erase(iterator it);//刪除it指向的字符,返回刪除后迭代器的位置 它僅刪除指定位置的一個字符。
代碼:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5 + 5;// 判斷是否是獨立的部分 bool judge(string &s, int x, int l) {if ((x == 0 || (!isdigit(s[x - 1]) && !isalpha(s[x - 1]))) && (x + l == s.length() || (!isdigit(s[x + l])&& !isalpha(s[x + l]))))return true;elsereturn false; }int main() {int T;cin >> T;getchar();while (T--) {string s;getline(cin, s);cout << s << endl;while (s[0] == ' ')s.erase(s.begin()); //去掉開頭的空格while (s[s.length() - 1] == ' ')s.erase(s.end() - 1); //去掉結尾的空格for (int i = 0; i < s.length(); i++) {if (s[i] == ' ') {while (s[i + 1] == ' ')s.erase(s.begin() + i + 1); //去掉多余空格if (!isdigit(s[i + 1]) && !isalpha(s[i + 1]))s.erase(s.begin() + i); //去掉標點前的空格}}for (int i = 0; i < s.length(); i++) {if (s[i] != 'I')s[i] = tolower(s[i]);}for (int i = 0;; i++) {i = s.find("can you", i);if (i == -1)break;if (judge(s, i, 7))s.replace(i, 7, "A can");}for (int i = 0;; i++) {i = s.find("could you", i);if (i == -1)break;if (judge(s, i, 9))s.replace(i, 9, "A could");}for (int i = 0;; i++) {i = s.find("I", i);if (i == -1)break;if (judge(s, i, 1))s.replace(i, 1, "you");}for (int i = 0;; i++) {i = s.find("me", i);if (i == -1)break;if (judge(s, i, 2))s.replace(i, 2, "you");}for (int i = 0; i < s.length(); i++) {if (s[i] == '?')s[i] = '!';else if (s[i] == 'A')s[i] = 'I';}cout << "AI: " << s << "\n";}return 0; }福到了 (字符串+翻轉)
題目練級
解題思路
代碼:
#include <iostream> #include <algorithm> #include <string> using namespace std; const int N = 110; string s[N], tp[N];int main() {char ch ;int n;cin >> ch >> n;getchar();for (int i = 0 ; i < n ; ++i)getline(cin, s[i]);for (int i = 0 ; i < n ; ++i )for (int j = 0 ; j < n; ++j)if (s[i][j] == '@')s[i][j] = ch;for (int i = 0 ; i < n ; ++i)tp[i] = s[i];for (int i = 0 ; i < n / 2 ; ++i) // 上下翻轉for (int j = 0 ; j < n ; ++j)swap(s[i][j], s[n - i - 1][j]);for (int i = 0 ; i < n ; ++i) // 左右翻轉reverse(s[i].begin(), s[i].end());bool flag = true;for (int i = 0 ; i < n ; ++i)if (tp[i] != s[i]) {flag = false;break;}if (flag)cout << "bu yong dao le" << endl;for (int i = 0 ; i < n ; ++i)cout << s[i] << endl;return 0; }數學模擬
特立獨行的幸福(模擬+map+素數)
題目鏈接
解題思路:
代碼:
#include<bits/stdc++.h> using namespace std; #define fir(i,a,n) for(int i=a;i<=n;i++) #define mem(a,x) memset(a,x,sizeof(a)); #define pb push_back typedef long long ll; const int N=1e4+10; int v[N];int l,r; map<int,int>mp,d; void solve(int x) {memset(v,0,sizeof(v));int xx=x;while(x!=1){int y=0;while(x){y+=((x%10)*(x%10));x/=10;}x=y;v[x]++; if(v[x]==2) return;//死循環 } x=xx;int t=0;while(x!=1){mp[x]++;int y=0;while(x){y+=((x%10)*(x%10));x/=10;}x=y; t++;}d[xx]=t; } int isp(int x) {for(int i=2;i<=sqrt(x);i++){if(x%i==0) return 0;}return 1; } int main() {cin>>l>>r;int ans=0;for(int i=l;i<=r;i++){solve(i);}for(int i=l;i<=r;i++){if(mp[i]==1){cout<<i<<" ";int t=d[i];if(isp(i)) t*=2;cout<<t<<endl;ans++;}}if(!ans) cout<<"SAD";return 0; }多項式除法
題目鏈接
對于多項式不了解的可以先百度了解一下。對于多項式除法,我們要做的就是將除數的高次冪消掉,直到除數的最高次數小于被除數的。
代碼:
#include <iostream> #include <algorithm>using namespace std; const int N = 1e5 + 10; int n, m, ma, mb; // ma的作用是記錄第一個多項式的最高次數。mb同理 double a[N], b[N], c[N]; // a中剩余的是余數 , c中為商int main() {cin >> n;int x, v;for (int i = 1 ; i <= n; ++i) {cin >> x >> v;ma = max(ma, x);a[x] = v;}cin >> m;for (int i = 1; i <= m ; ++i) {cin >> x >> v;mb = max(mb, x);b[x] = v;}int t1 = ma, t2 = mb;while (t1 >= t2) {double t = a[t1] / b[t2];c[t1 - t2] = t;for (int i = t1, j = t2; j >= 0 ; --i, --j)a[i] -= b[j] * t;while (abs(a[t1]) < 0.000001)t1--;}int maxn, cnt = 0;for (int i = 0 ; i <= ma ; ++i)if (abs(c[i]) >= 0.05) {maxn = i;cnt++;}if (cnt) {cout << cnt;for (int i = maxn ; i >= 0 ; --i)if (abs(c[i]) >= 0.05)printf(" %d %.1lf", i, c[i]);cout << endl;} elseprintf("0 0 0.0\n");maxn = 0, cnt = 0;for (int i = 0; i <= mb ; ++i)if (abs(a[i]) >= 0.05) {maxn = i ;cnt++;}if (cnt) {cout << cnt;for (int i = maxn ; i >= 0; --i)if (abs(a[i]) >= 0.05)printf(" %d %.1lf", i, a[i]);cout << endl;} elseprintf("0 0 0.0\n");return 0; }N個數求和
題目鏈接
解題思路:
對于分式加法我們就是通分后再相加。
代碼:
#include <iostream> #include <cmath> #include <algorithm> #include <string> using namespace std; typedef long long LL; const int N = 10010; int n ; LL A, B, L; string s;LL gcd(LL a, LL b) {if (!b)return a;elsereturn gcd(b, a % b); }LL lcm(LL a, LL b) {return a / gcd(a, b) * b; }void simply(LL A, int B) {L = gcd(A, B);A /= L, B /= L; }int main() {cin >> n;A = 0, B = 1;while (n--) {LL a = -1, b, f = 1, st = 0, num = 0;cin >> s;if (s[0] == '-')f *= -1, st = 1;s += " "; // 后面添加一個字符方便結束for (int i = st ; i < (int)s.size() ; ++i) {if (s[i] >= '0' && s[i] <= '9')num = num * 10 + s[i] - '0';else {if (a == -1)a = num;elseb = num;num = 0;}}a *= f;L = lcm(B, b);A = A * L / B + a * L / b;B = L;simply(A, B);}simply(A, B);LL val = A / B ;A %= B;if (val) {if (A)cout << val << " ";elsecout << val << endl;}if (A)cout << A << '/' << B << endl;if (!val && !A)cout << 0 << endl;return 0; }矩陣乘法
題目鏈接
解題思路
首先我們要理解,為什么需要前一個舉證的列數等于后一個矩陣的行數。由矩陣乘法的定義我們知道對于 ,在求解新矩陣某一個位置的值的時候(i,k),是由其在 前一個矩陣的第i行與后一個矩陣的第k列進行得到,由于這個操作是行中所有元素與列中元素相乘的和得到。因此行中元素需要和列中元素相等。也就前一個矩陣的列數 === 后一個矩陣的行數。
代碼:
#include <iostream> #include <algorithm> #include <cmath> using namespace std;const int N = 1010;int ra, ca, rb, cb; int a[N][N], b[N][N], c[N][N];int main() {cin >> ra >> ca;for (int i = 1 ; i <= ra ; ++i)for (int j = 1 ; j <= ca ; ++j)cin >> a[i][j];cin >> rb >> cb;for (int i = 1 ; i <= rb ; ++i)for (int j = 1 ; j <= cb ; ++j)cin >> b[i][j];if (ca != rb)cout << "Error: " << ca << " != " << rb << endl;else {for (int i = 1 ; i <= ra ; ++i) {for (int k = 1 ; k <= cb ; ++k) {for (int j = 1 ; j <= ca ; ++j)c[i][k] += a[i][j] * b[j][k];}}cout << ra << " " << cb << endl;for (int i = 1 ; i <= ra ; ++i) {int f = 0;for (int j = 1 ; j <= cb ; ++j) {if (f)cout << " ";cout << c[i][j], f++;}cout << endl;}}return 0; }技巧模擬
天梯賽座位分配 (模擬 + 技巧)
題目鏈接
解題思路:
由于對于每一個學校來說,隊伍是按順序來排的,因此我們就直接記錄每一個學校的總人數(對伍數量 * 10)
之后的關鍵點是在操作的時候我們用一個數取存上一次操作的學校標號,如果與當前一樣就說明只剩下了一個學校了。
代碼:
#include <iostream> #include <algorithm> #include <cstring> using namespace std;const int N = 4100; int n; struct node {int pos[N];int cnt, tot; } p[N];bool check() {int ans = 0;for (int i = 1 ; i <= n ; ++i)if (p[i].tot == 0)ans++;return ans == n ; }int main() {cin >> n;for (int i = 1 ; i <= n ; ++i) {int x;cin >> x;p[i].tot = x * 10;}int cnt = 0;int last = -1;while (1) {for (int i = 1 ; i <= n ; ++i)if (p[i].tot) {if (i == last)cnt += 2;elsecnt ++;int &x = p[i].cnt;p[i].pos[++x] = cnt;p[i].tot--;last = i ;}if (check())break;}for (int i = 1; i <= n ; ++i) {cout << "#" << i << endl;int f = 0;for (int j = 1 ; j <= p[i].cnt; ++j) {if (f)cout << " ";cout << p[i].pos[j];f++;if (f && f % 10 == 0)cout << endl, f = 0;}if (f)cout << endl;}return 0; }倒數第N個字符串(數學知識 + 技巧)
題目鏈接
解題思路:
代碼:
#include <iostream> #include <algorithm> #include <cstring> using namespace std;int ans[30];int main() {int L, n;cin >> L >> n;n--;int cnt = 0;while (n) {ans[L - cnt - 1] = n % 26;n /= 26;cnt ++;}for (int i = 0 ; i < L ; ++i) {printf("%c", 'z' - ans[i]);}cout << endl;return 0; }秀恩愛分得快
題目鏈接
解題思路:
代碼:
#include <iostream> #include <queue> #include <stack> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <vector> #include <algorithm> #define Mod 19999997 typedef long long ll; using namespace std; bool flag[1005];int read() {int input = 0, sign = 0;char a = getchar();while ((a < '0' || a > '9') && a != '-')a = getchar();if (a == '-') {sign = 1;a = getchar();}while (a >= '0' && a <= '9') {input = input * 10 + a - '0';a = getchar();}flag[input] = sign; //女性用true標記return input; }int main() {int n, m;while (scanf("%d%d", &n, &m) != EOF) {memset(flag, false, sizeof(flag));vector<vector<int> >p(n); //存儲所有照片vector<double> PA(n, 0.0), PB(n, 0.0); //與A的親密度,與B的親密度int coloum;for (int i = 0; i < m; ++i) {scanf("%d", &coloum);p[i].resize(coloum);for (int j = 0; j < coloum; ++j) {p[i][j] = read();}}int A, B;A = read(), B = read();double MAXA = 0.0, MAXB = 0.0;for (int i = 0; i < m; ++i) {bool FindA = find(p[i].begin(), p[i].end(), A) != p[i].end(); //查找Abool FindB = find(p[i].begin(), p[i].end(), B) != p[i].end(); //查找Bif (FindA || FindB) {for (int j = 0; j < p[i].size(); ++j) {if (FindA && flag[A] != flag[p[i][j]]) { // 有A 且性別不一樣PA[p[i][j]] += (double)1.0 / p[i].size(); //親密度累加MAXA = max(MAXA, PA[p[i][j]]); //最大親密度} else if (FindB && flag[B] != flag[p[i][j]]) {PB[p[i][j]] += (double)1.0 / p[i].size();MAXB = max(MAXB, PB[p[i][j]]);}}}}if (MAXA == PA[B] && MAXB == PB[A]) { //彼此親密度最高printf("%s%d %s%d\n", flag[A] ? "-" : "", A, flag[B] ? "-" : "", B);} else {for (int i = 0; i < n; i++) {if (PA[i] == MAXA) {printf("%s%d %s%d\n", flag[A] ? "-" : "", A, flag[i] ? "-" : "", i);}}for (int i = 0; i < n; i++) {if (PB[i] == MAXB) {printf("%s%d %s%d\n", flag[B] ? "-" : "", B, flag[i] ? "-" : "", i);}}}} }其余
名人堂與代金券(技巧)
題目鏈接
解題思路:
這題就是一個自定義排序問題。
對于這題的關鍵點我認為是在排名上面,解決技巧是我們在排序后對每一個人先標上編號。之后對于值相等的我們將后一個的排名令其與前一個相同。之后在輸出的時候,輸出排名不大于k的即可。
代碼:
#include <iostream> #include <string> #include <algorithm> #include <cmath> using namespace std; const int N = 1E4 + 19;struct node {string s;int val, rade;bool operator < (node w) {if (w.val == val)return s < w.s;return val > w.val;} } p[N];int main() {int n, g, k;int sum = 0;cin >> n >> g >> k;for (int i = 0 ; i < n ; ++i) {cin >> p[i].s >> p[i].val;if (p[i].val >= 60 && p[i].val < g)sum += 20;else if (p[i].val >= g && p[i].val <= 100)sum += 50;}sort(p, p + n);cout << sum << endl;for (int i = 0 ; i < n ; ++i)p[i].rade = i + 1;for (int i = 0 ; i < n - 1 ; ++i)if (p[i].val == p[i + 1].val)p[i + 1].rade = p[i].rade;for (int i = 0 ; p[i].rade <= k && i < n ; ++i)cout << p[i].rade << " " << p[i].s << " " << p[i].val << endl;return 0; }刮刮彩票
題目鏈接
解題思路:
代碼:
#include<iostream> #include<algorithm> #include<cstring> using namespace std;int g[10][10]; bool st[10][10] , bk[10]; int xx , yy; int money[25] = {0,0,0,0,0,0,10000,36,720,360,80,252,108,72,54,180,72,180,119,36,306,1080,144,1800,3600};int main(){int n = 3;for(int i = 1; i <= n ; ++i)for(int j = 1 ; j <= n ; ++j){int x ;cin>>x;if(!x) st[i][j] = 1 ,xx =i , yy = j;else {g[i][j] = x , bk[x] = 1;}}for(int i = 1; i <= 9 ; ++i)if(!bk[i])g[xx][yy] = i ;for(int i = 1 ; i <= 3 ; ++i){cin>>xx>>yy;st[xx][yy] = 1;cout<<g[xx][yy]<<endl;}int op , ans = 0 ;cin>>op;if(op >= 1 && op <= 3){ for(int j = 1 ; j <= n ; ++j) ans += g[op][j];}else if(op >= 4 && op <= 6){for(int i = 1 ; i <= 3 ; ++i)ans += g[i][op-3];}else if(op == 7) { for(int i = 1 ; i <= 3 ; ++i) ans += g[i][i];}else for(int i = 1 ; i <= 3 ; ++i) ans += g[i][n-i+1];cout<<money[ans]<<endl;return 0; }總結
以上是生活随笔為你收集整理的PTA团体程序设计天梯赛篇(一)----模拟专题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 算法之组合数学及其算法篇(三) ----
- 下一篇: acwing----春季每日一题2022