日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PTA团体程序设计天梯赛篇(一)----模拟专题

發布時間:2025/3/19 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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、判斷與轉換函數

  • isdigit:判斷是否是數字
  • isalpha:判斷是否是字母
  • tolower:大寫轉化為小寫
  • 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;}

    敲笨鐘(字符串查找+字符串替換)

    題目鏈接

    解題思路:

  • 對于找有押韻的句子,我們的目標是前后兩句的結尾都有ong的句子。那么由于這題的句子格式是固定的,因此我們通過找ong, 判斷前一個是否有,ong.則是后一個。
  • 對于替換的位置,我們可以從后面開始數空格數,當空格數是第三個的時候的位置為所求,同時當前位置是空格的位置,如果我們直接替換的話,會將空格消去,因此正確位置應該往后加一。
  • 代碼:

    #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指向的字符,返回刪除后迭代器的位置 它僅刪除指定位置的一個字符。

  • 去除首位空格的方法,我們只需要在首部或者尾部,進行刪除,直到不是空格就可以了。
  • 去除單詞之間的多余空格和標點符號前的所有字符:對于兩個單詞間的,當我們匹配到一個空格之后,開始判斷下一個是否是空格,如果是的話刪除(循環) ,對于標點符號,由于是前面不能留空格,那么如果我們在進行上面刪除多余空格的操作后,如果后邊的字符如果不是數字和字母(就是標點符號)那么我們就可以刪除當前位置的空格。
  • 后面替換操作的注意事項:要注意的是 can you、could you 換成了 can I、could I 后,這里的 I 不能再換成 you 了,所以可以先換成其他字符比如 ‘A’ 。替換是要注意判斷它們是不是一個獨立的部分,也就是說如果它們包含在兩個單詞之中,那么它就不能被替換。
  • 代碼:

    #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; }

    福到了 (字符串+翻轉)

    題目練級

    解題思路

  • 對于順時針旋轉180度來說,可以先上下翻轉,之后左右翻轉即可。(本題只是順時針)。補充:對于逆時針,則是先左右翻轉,再上下翻轉。
  • 對于左右翻轉可以利用reverse函數。
  • 代碼:

    #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+素數)

    題目鏈接

    解題思路:

  • 對于不是幸福數的判斷方法就是,在循環的時候出現重復的就不是了。
  • 當我們判斷完一個數是幸福數之后,我們將其本身和在生成1的過程中產生的數進行記錄。如果出現次數為1就是特立獨行的幸福數了。
  • 代碼:

    #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個數求和

    題目鏈接

    解題思路:
    對于分式加法我們就是通分后再相加。

  • 處理字符部分,一個是我們可以利用scanf的特性可以直接讀入。當然也可以當成字符串來處理。
  • 這里惡心的是輸出的格式,當整數部分為0且小數部分也是0就輸出0.如果整數部分不為0,但小數部分為0,則只輸出整數部分。
  • 代碼:

    #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個字符串(數學知識 + 技巧)

    題目鏈接

    解題思路:

  • 由于這個題目是倒數的,所以我們令0位z,25位a , 也就是 ‘z’- val對應的字符。
  • 對于這個題目我們可以發現,對于最后一位是以26為一個周期的,而第二位這就是26*26 ,第三位則是 26 * 26 * 6 … 因此我們可以發現這類似于一個26進制。
  • 補充: 如果是順數的話,我們也是初始化為0,只不過由減法變成加法 ‘a’ + val
  • 代碼:

    #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; }

    秀恩愛分得快

    題目鏈接

    解題思路:

  • 為了避免超時我們不能都算,而是先存起來,之后只算與A,B有關的。
  • 由于會有-0的情況因此需要用字符串進行讀取,之后取正值并對這個值進行標記。
  • 對于計算,我們遍歷所有的照片,利用find函數,找是否含有A或B,如果有,對與其異性的值進行計算親密度,同時記錄最大的親密度。
  • 代碼:

    #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团体程序设计天梯赛篇(一)----模拟专题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。