題目鏈接:https://pintia.cn/problem-sets/994805046380707840/problems/type/7?page=0
基礎級:L1-057~064
進階級:L2-029~032
登頂級:L3-022~024
題目說明:
前七題:水題,字符串,
估值一億的AI核心代碼(大模擬)
特立獨行的幸福(暴力模擬) 冰島人(暴力|LCA)
深入虎穴(最長路) 彩虹瓶(水題-模擬)
emmmm,懷念當年我還是大一的時候啊,現在的我已經是個混吃等死的死宅了QAQ,總的來說當年這套題似乎也不是很難,我這種蒟蒻學了半年也能寫個110+的分數。。。想當時寫完我還自閉了好久,拖了隊伍的后退啊QAQ。。。
基礎級:
總的來說沒什么難的,當然除了最后一題。。。。最后一題調太久了而且最終還沒出來,要是當時直接扔了也不至於分數這么低,前面的七題大概半個小時就差不多了。
PTA使我精神煥發(5)
沒什么好說的,直接printf就完事了
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; int main() { printf ("PTA shi3 wo3 jing1 shen2 huan4 fa1 !\n"); return 0; }
6翻了(15)
沒什么好說的,就是不能用gets,那么只能換getline並用string來解決了,我們for一遍直接處理就好了
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; const int mac=1e3+10; string s; int main() { getline(cin,s); int len=s.length(); for (int i=0; i<len; i++){ if (s[i]=='6'){ int j,mis=0; for (j=i; j<len; j++){ if (s[j]!='6') break; mis++; } i=j; if (mis<=3) for (int k=1; k<=mis; k++) printf("6"); else if (mis>3 && mis<=9) printf("9"); else printf("27"); } printf("%c",s[i]); } printf("\n"); return 0; }
敲笨鍾(20)
也沒什么好說的,讀一句處理一句就好了,至於怎么處理,直接暴力來就完事了,值得注意的一點是讀入整數過后要用getchar將回車吃掉,不然第一個字符串就是回車符了
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; string s; int main() { int n; scanf ("%d",&n); getchar(); for (int i=1; i<=n; i++){ getline(cin,s); int len=s.length()-1; int mid,mark=0; for (int j=0; j<=len; j++) if (s[j]==',') mid=j; if (s[mid-1]=='g' && s[mid-2]=='n' && s[mid-3]=='o') if (s[len-1]=='g' && s[len-2]=='n' && s[len-3]=='o'){ mark=1; int pos,space=0; for (int j=len; j>mid; j--){ if (s[j]==' ') space++; if (space==3) {pos=j;break;} } for (int j=0; j<=pos; j++) printf("%c",s[j]); printf("qiao ben zhong.\n"); } if (!mark) printf("Skipped\n"); } return 0; }
心理陰影面積(5)
沒什么好說的,就是一個大三角形減去小三角形再減去一個梯形就完事了,值得注意的是這里的面積運算都要使用int型,最后的結果也是int型
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; int main() { int x,y; int tot=100*100/2; scanf ("%d%d",&x,&y); int s1=(100-x)*(100-y)/2; int s2=(100+100-x)*y/2; printf("%d\n",tot-s1-s2); return 0; }
新胖子公式(10)
emmmm,沒什么好說的了,不要加上精度誤差就能過
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; int main() { double weight,heigt; cin>>weight>>heigt; double ans=(weight/(heigt*heigt)); printf("%.1f\n",ans); if (ans>25) printf("PANG\n"); else printf("Hai Xing\n"); return 0; }
幸運彩票(15)
這個也很簡單,直接看代碼
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; char s[10]; int solve(char c1,char c2,char c3) { int p1=c1-'0',p2=c2-'0',p3=c3-'0'; return p1+p2+p3; } int main() { int n; scanf ("%d",&n); for (int i=1; i<=n; i++){ scanf ("%s",s); int s1=solve(s[0],s[1],s[2]); int s2=solve(s[3],s[4],s[5]); if (s1==s2) printf("You are lucky!\n"); else printf("Wish you good luck.\n"); } return 0; }
吃魚還是吃肉(10)
沒什么好說的,if-else判斷即可,復制粘貼別出錯就行了
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; int main() { int n; scanf ("%d",&n); for (int i=1; i<=n; i++){ int sx,height,weight; scanf ("%d%d%d",&sx,&height,&weight); if (sx==1){ if (height>130) printf("ni li hai! "); else if (height==130) printf("wan mei! "); else printf("duo chi yu! "); if (weight>27) printf("shao chi rou!\n"); else if (weight==27) printf("wan mei!\n"); else printf("duo chi rou!\n"); } else { if (height>129) printf("ni li hai! "); else if (height==129) printf("wan mei! "); else printf("duo chi yu! "); if (weight>25) printf("shao chi rou!\n"); else if (weight==25) printf("wan mei!\n"); else printf("duo chi rou!\n"); } } return 0; }
估值一億的AI核心代碼(20)
emmmm,當時記得調了很久,現在看來。。。也不是很難,我們先做最簡單的替換,也就是將大寫變小寫(除了I),將“?”變成“!”,接下來我們必須先解決多余的空格問題,這個也不是很難,我們先搞定頭尾,這個就很簡單了,那么得出的新的頭尾設為head和tail。然后我們從head到tail直接for一遍一旦碰到非空格的我們就一直往下讀,遇到空格,我們要進行一個簡單的判斷,先往下讀,讀到非空格,判斷這個字符是不是數字和字母,(標點符號非常多,難以判斷),如果是的話我們就直接在新的字符串中添加一個空格,如果不是的話我們直接break:
string ss; int head=0,tail=len-1; while (s[head]==' ') head++;//空格消除 while (s[tail]==' ') tail--; for (int i=head; i<=tail; i++) { int j; if (letter(s[i]) || number(s[i])) { for (j=i; j<=tail; j++) { if (!letter(s[j]) && !number(s[j])) break; ss+=s[j]; } i=j-1; } else if (s[i]==' ') { for (j=i; j<=tail; j++) { if (letter(s[j]) || number(s[j])) { ss+=' '; break; } else if (s[j]!=' ') break; } i=j-1; } else ss+=s[i]; }
這樣得到的ss就是一個比較完美的無多余空格的字符串,那么現在我們就只剩下替換I,me,can you,could you了,當然我們如果直接替換的話會有一定的難度,所以我們可以換一種方法思考,我們可以對要替換的單詞進行標記然后就沒了。標記過程如下:
int lens=ss.length(); for (int i=0; i<lens; i++) { //標記I,me,can you,could you的位置 if (ss[i]=='I') { if (i==0 && !letter(ss[i+1]) && !number(ss[i+1])) id[i]=1; else if (ss[i-1]==' ' && !letter(ss[i+1]) && !number(ss[i+1])) id[i]=1; } else if (ss[i]=='m' && ss[i+1]=='e') { if (i==0 && !letter(ss[i+2]) && !number(ss[i+2])) id[i]=2; else if (ss[i-1]==' ' && !letter(ss[i+2]) && !number(ss[i+2])) id[i]=2; } else if (can(ss,i)) id[i]=3; else if (could(ss,i)) id[i]=4; }
那么接下來就是編寫letter,number,can,could這4個判斷函數了
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; string s; int id[1010]; //1--表示I,2--表示me,3表示can you,4表示could you char cny[]={'c','a','n',' ','y','o','u'}; char cdy[]={'c','o','u','l','d',' ','y','o','u'}; int letter(char c)//判斷字母 { if (c>='a' && c<='z') return 1; if (c>='A' && c<='Z') return 1; return 0; } int number(char c)//判斷數字 { if (c>='0' && c<='9') return 1; return 0; } int can(string ss,int st)//判斷是否為獨立的can you { if (st==0){ for (int i=0; i<7; i++) if (ss[i+st]!=cny[i]) return 0; if (letter(ss[st+7]) || number(ss[st+7])) return 0; } else { if (ss[st-1]!=' ') return 0; for (int i=0; i<7; i++) if (ss[i+st]!=cny[i]) return 0; if (letter(ss[st+7]) || number(ss[st+7])) return 0; } return 1; } int could(string ss,int st)//判斷是否為獨立的could you { if (st==0){ for (int i=0; i<9; i++) if (ss[i+st]!=cdy[i]) return 0; if (letter(ss[st+9]) || number(ss[st+9])) return 0; } else { if (ss[st-1]!=' ') return 0; for (int i=0; i<9; i++) if (ss[i+st]!=cdy[i]) return 0; if (letter(ss[st+9]) || number(ss[st+9])) return 0; } return 1; } int main() { int n; scanf ("%d",&n); getchar(); while(n--){ getline(cin,s); cout<<s<<endl; cout<<"AI: "; memset(id,0,sizeof id); int len=s.length(); for (int i=0; i<len; i++){//簡單替換 if (letter(s[i])) if (s[i]<'a' && s[i]!='I') s[i]+=32; if (s[i]=='?') s[i]='!'; } string ss; int head=0,tail=len-1; while (s[head]==' ') head++;//空格消除 while (s[tail]==' ') tail--; for (int i=head; i<=tail; i++){ int j; if (letter(s[i]) || number(s[i])){ for (j=i; j<=tail; j++){ if (!letter(s[j]) && !number(s[j])) break; ss+=s[j]; } i=j-1; } else if (s[i]==' '){ for (j=i; j<=tail; j++){ if (letter(s[j]) || number(s[j])) {ss+=' '; break;} else if (s[j]!=' ') break; } i=j-1; } else ss+=s[i]; } //得到的ss無多余空格 int lens=ss.length(); for (int i=0; i<lens; i++){//標記I,me,can you,could you的位置 if (ss[i]=='I'){ if (i==0 && !letter(ss[i+1]) && !number(ss[i+1])) id[i]=1; else if (ss[i-1]==' ' && !letter(ss[i+1]) && !number(ss[i+1])) id[i]=1; } else if (ss[i]=='m' && ss[i+1]=='e'){ if (i==0 && !letter(ss[i+2]) && !number(ss[i+2])) id[i]=2; else if (ss[i-1]==' ' && !letter(ss[i+2]) && !number(ss[i+2])) id[i]=2; } else if (can(ss,i)) id[i]=3; else if (could(ss,i)) id[i]=4; } for (int i=0; i<lens; i++){ if (!id[i]) cout<<ss[i]; else if (id[i]==1) cout<<"you"; else if (id[i]==2) {cout<<"you"; i++;} else if (id[i]==3) { cout<<"I can"; i+=6; } else if (id[i]==4){ cout<<"I could"; i+=8; } } cout<<endl; } return 0; }
進階級:
emmm,也基本都是水題,除了冰島人有點惡心人。。。我想當初我要是扔掉大模擬那題那得加多少分啊QAQ!!!
特立獨行的幸福(25)
emmm,乍一看還有點蒙,不過按照他的要求來的話也不是很難,就是感覺有點難的樣子。。。。我們直接暴力就可以了,在區間內尋找,然后在尋找的過程中進行標記,對於已經標記過的點就直接扔了,也是挺簡單的一題
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; const int mac=1e4+10; int prim[mac],vis[mac],num[mac]; bool mk[mac]; int solve(int m) { int tot=0; while (m){ int p=m%10; tot+=p*p; m/=10; } return tot; } int ok(int s,int m) { memset(mk,false,sizeof mk); mk[m]=true; while (m!=1){ m=solve(m); if (mk[m]) return -1; mk[m]=true;vis[m]=1; s++; } return s-1; } int main() { int l,r; int p=sqrt(mac); for (int i=2; i<=p; i++) if (!prim[i]) for (int j=i*i; j<=mac; j+=i) prim[j]=1; scanf ("%d%d",&l,&r); for (int i=l; i<=r; i++){ if (vis[i]) continue; num[i]=ok(1,i); } int yes=0; for (int i=l; i<=r; i++){ if (vis[i]) continue; if (num[i]<1) continue; if (!prim[i]) yes=1,printf ("%d %d\n",i,num[i]*2); else yes=1,printf ("%d %d\n",i,num[i]); } if (!yes) printf ("SAD\n"); return 0; }
冰島人(25)
首先,看題目。。。。真的看了很久。。。看不懂QAQ,所謂的其他人不知道指的是什么,題目說保證維京人的起源都是男性m,那么f是個什么鬼?直接當場去世。。。。所謂的五代以內也有點疑惑
好吧,題目還是要做的。。。。硬着頭皮肝了一下,既然說起源都是男性m,那么f應該沒什么用了吧,扔掉后跑了一遍。。。19分,加上f,把她當祖宗另加一個if-else判斷末尾。。。23分,原來過了測試點的沒過,我。。。。
然后我就想了想,只改變性別試試,至於她的姓可以和m的一樣,這樣就可以最大限度地保持原來代碼的模樣,結果一下子就過了。。。。真是蜜汁WA
不過本題的數據感覺有點水。。。本來想用LCA的,結果直接暴力都可以過,這里先將其中一個點的所有父親都找出來,並打上標記,附上到每個點的距離。然后跑另一個點就完事了。
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; const int mac=1e5+10; struct node { string ming,xing; int sx;//0女,1男 }name[mac]; int fa[mac]; unordered_map<string,int>q1,q2; int same(string s1,string s2,int id1,int id2) { unordered_map<int,int>dis,vis; dis[id1]=1;vis[id1]=1; int p=1; while(fa[id1]!=-1){ id1=fa[id1]; dis[id1]=++p; vis[id1]=1; if (id1==id2) return 0; } p=1; while (fa[id2]!=-1){ id2=fa[id2]; ++p; if (vis[id2]){ if (dis[id2]>4 && p>4) return 1; else return 0; } } return 1; } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int n; cin>>n; memset(fa,-1,sizeof fa); for (int i=1; i<=n; i++){ string s1,s2; cin>>s1>>s2; q1[s1]=i; int len2=s2.length(); if (s2[len2-1]=='n'){ name[i].sx=1; name[i].ming=s1; name[i].xing=s2.substr(0,len2-4); } else if (s2[len2-1]=='r'){ name[i].sx=0; name[i].ming=s1; name[i].xing=s2.substr(0,len2-7); } else { name[i].ming=s1; if (s2[len2-1]=='m') name[i].sx=1; else name[i].sx=0; name[i].xing="m"; } } for (int i=1; i<=n; i++){ if (name[i].xing=="m") continue; fa[i]=q1[name[i].xing]; if (!fa[i]) fa[i]=-1; } int m; cin>>m; while (m--){ string ming1,xing1,ming2,xing2; cin>>ming1>>xing1>>ming2>>xing2; if (!q1[ming1] || !q1[ming2]){ cout<<"NA"<<endl; continue; } if (name[q1[ming1]].sx==name[q1[ming2]].sx){ cout<<"Whatever"<<endl; continue; } if (same(ming1,ming2,q1[ming1],q1[ming2])){ cout<<"Yes"<<endl; continue; } cout<<"No"<<endl; } return 0; }
深入虎穴(25)
emmmm,看起來不是很難,確實也不是很難,就是坑了點,首先就是入口不知道(我剛開始一直以為是1)QAQ,實際上是沒有入度的點,接下來就是他有一個n=1的數據。。。。那么最短距離就是0。。。我在這兩個地方栽了一回。實際上就是跑個dij改編的最長路就完事了。
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; const int mac=1e5+10; struct node { int to,w,next; }eg[mac<<2]; struct way { int id,s; bool operator <(const way&a)const{ return s<a.s; } }; int head[mac],num=0,dis[mac],vis[mac],n; int fa[mac]; void add(int u,int v) { eg[++num]=node{v,1,head[u]}; head[u]=num; } void dij(int id) { priority_queue<way>q; q.push(way{id,0}); while (!q.empty()){ way now=q.top(); q.pop(); int u=now.id; for (int i=head[u]; i!=-1; i=eg[i].next){ int v=eg[i].to; if (dis[u]+eg[i].w>dis[v]) { dis[v]=dis[u]+eg[i].w; q.push(way{v,dis[v]}); } } } int mx=-1,mxid; for (int i=1; i<=n; i++) if (dis[i]>mx) mx=dis[i],mxid=i; printf("%d\n",mxid); } int main() { scanf ("%d",&n); memset(head,-1,sizeof head); for (int i=1; i<=n; i++){ int m; scanf ("%d",&m); for (int j=1; j<=m; j++){ int v; scanf ("%d",&v); fa[v]=i; add(i,v); } } for (int i=1; i<=n; i++) if (!fa[i]){ dij(i);break; } return 0; }
彩虹瓶(25)
emmm,像這種沒有罰時的情況下我們可以寫個隨機數去多跑幾遍,至於得幾分那就看命了QAQ
先看題目。。。。有點長,看完之后覺得。。。太簡單了!寫一發。。。。確實簡單,用個簡單的棧模擬一下過程跑一跑就完事了
以下是AC代碼:

#include <bits/stdc++.h> using namespace std; int id[1010],sstack[1010]; int main() { int n,m,s; scanf ("%d%d%d",&n,&m,&s); while (s--){ for (int i=1; i<=n; i++) scanf ("%d",&id[i]); int tail=0,use=1,mark=0; for (int i=1; i<=n; i++){ if (id[i]==use) use++; else { while (tail && sstack[tail-1]==use) {use++; tail--;} if (id[i]==use) {use++; continue;} sstack[tail++]=id[i]; if (tail>m) {mark=1; printf("NO\n"); break;} } } while (tail && sstack[tail-1]==use) {use++; tail--;} if (!mark & !tail) printf("YES\n"); else if (!mark) printf("NO\n"); } return 0; }
登頂級:
emmm。。。。有點懶了,下次一定記得補
地鐵一日游
計算圖
Oriol和David