PAT甲級題
1001 A+B Format (20)
輸入兩個整數a,b(-1000000 <= a, b <= 1000000),輸出a+b,按指定格式輸出,就是每三位要用”,”隔開。
簡單題,printf %0nd 就是前補n個零的輸出。
1002 A+B for Polynomials (25)
輸入兩個多項式,題目保證指數的輸入是遞減的。輸出兩個多項式的和,格式和輸入時候一樣。
多項式指數n<=1000,項數k<=10。
簡單題。模擬即可。
1003 Emergency (25)(最短路)
給一個無向圖,每個頂點有一個價值,求解從s到t有幾條最短路,然後求出這幾條最短路中,總價值最高的價值。
我們從根開始dfs,把每個結點的深度存下來,level[x]代表著x這個結點的深度。做完這以後,我們知道葉子結點的特點是什麼,就是他沒有孩子結點,那麼在我們的儲存方式中 等價於 G[i].size()=0。因為G[i]儲存的是i這個結點的孩子節點。所以dfs的過程中發現G[i].size()==0就可以在這一層的計數器上+1了,也就是cnt[lv]++。
#include <bits/stdc++.h>
using namespace std;
const int maxn_v = 500 + 5;
const int INF = 0x3f3f3f3f;
typedef pair<int , int>pii;
struct Edge{int to, w;};
vector<Edge>G[maxn_v];
int people[maxn_v], dis[maxn_v], vis[maxn_v], path[maxn_v], gather[maxn_v];
void dijkstra(int vs, int es, int s, int t)
{
for(int i = 0; i < vs; i++) dis[i] = INF, vis[i] = 0, path[i] = 1, gather[i] = people[i];
priority_queue<pii, vector <pii>, greater<pii>>que;
dis[s] = 0;
que.push({0, s});
while(que.size())
{
pii cur = que.top();que.pop();
int u = cur.second, w = cur.first;
if(vis[u]) continue;
vis[u] = 1;
for(auto o : G[u])
{
if(dis[u] + o.w < dis[o.to])
{
dis[o.to] = dis[u] + o.w;
que.push({o.to, dis[o.to]});
path[o.to] = path[u];
if(gather[o.to] < gather[u] + people[o.to])
{
gather[o.to] = gather[u] + people[o.to];
}
que.push({dis[o.to], o.to});
}
else if(dis[u] + o.w == dis[o.to])
{
path[o.to] += path[u];
if(gather[o.to] < gather[u] + people[o.to])
{
gather[o.to] = gather[u] + people[o.to];
}
}
}
}
cout << path[t] << " " << gather[t] << endl;
}
int main()
{
int vs, es, s, t;
scanf("%d%d%d%d", &vs, &es, &s, &t);
for(int i = 0; i < vs; i++) scanf("%d", &people[i]);
for(int i = 0; i < es; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
G[u].push_back({v, w});
G[v].push_back({u, w});
}
dijkstra(vs, es, s, t);
return 0;
}
1004 Counting Leaves (30)(dfs)
給你一棵有根數,問這棵樹每一層葉子結點的數量,結點數量n<=500.
n這麼小,直接搜就行了
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100 +5;
typedef pair<int, int>pii;
int maxlv;
int level[maxn];
int cnt[maxn];
vector<int>G[maxn];
void dfs(int cur, int lv)
{
level[cur] = lv;
maxlv = max(maxlv, lv);
if(G[cur].size() == 0) cnt[lv]++;//如果它沒有孩子,說明它這一層沒有孩子的結點數++
for(auto o : G[cur]) dfs(o, lv + 1);
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
while(m--)
{
int pa, num;
scanf("%d%d", &pa, &num);
while(num--)
{
int ch;
scanf("%d", &ch);
G[pa].push_back(ch);
}
}
maxlv = 0;
dfs(1, 0);
for(int i = 0; i <= maxlv; i++)
{
printf("%d%c", cnt[i], i == maxlv ? '\n' : ' ');
}
return 0;
}
1005 Spell It Right (20)
出一個不大於10^100數,將各位數字相加的和用英文輸出。
1006 Sign In and Sign Out (25)
給出n個人的id、sign in時間、sign out時間,求最早進來的人和最早出去的人的ID。(id長度<15)
把每個人sign in,sign out的時間都算出來,存一下,排序兩次即可。
1007 Maximum Subsequence Sum (25)(最大欄位和)
求最大子段和,輸出最大的和以及這個子段的開始值和結束值。如果所有數都小於0,那麼認為最大的和為0,並且輸出首尾元素。
經典dp。細節略微小心一下即可。有些許坑點。
1008 Elevator (20)
有一個電梯上下跑,電梯升高一層需要6秒,下降一層需要4秒。每次停下電梯將花費5秒。一開始電梯在0層,有n次請求,每次請求後電梯會跑到那一層,最後電梯不需要回到底層。問總共花了多少時間,所有資料範圍<=100。
1009 Product of Polynomials (25)
多項式乘法,多項式長度n<=1000.
模擬即可。
1010 Radix (25)(難題)
1011 World Cup Betting (20)
給出三行資料,代表三場比賽。每行有三個浮點整數,從左至右分別代表W(Win)、T(Tie)、L(Lost)。現在需要從每行的 W、T、L 中選擇最大的數,並輸出三行各自選擇的是哪一個。並輸出(三個數相乘*0.65-1)*2,保留兩位小數。
1012 The Best Rank (25)
已知n名考生的ID,c語音,數學,英語成績,進行m次查詢,輸出給定ID的學生,在三門課或者平均成績中獲得的最高排名,以及哪一門。
1013 Battle Over Cities (25)(並查集or深搜)
從一個無向圖裡頭,取出一個頂點,至少要補幾條邊能夠使得它聯通。
我們畫幾個圖就很容易明白,n個結點如果想要聯通,必然至少需要n-1條邊。那麼如果是n個塊(一個塊有若干個聯通的結點)呢,是不是也是如此。這裡就有一個連通分量的概念。然後我們怎麼去看有幾個塊呢,顯然並查集和dfs都是極好的。
這裡只講dfs,其實題目很簡單,就是最入門的dfs題,想一下剛學dfs時候的八連通,四聯通的題目,只需要dfs和vis標記即可。
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1000 +5;
typedef pair<int, int>pii;
int attack;
int vis[maxn];
vector<int>G[maxn];
void dfs(int cur)
{
vis[cur] = 1;
for(auto o : G[cur]) if(vis[o] == 0 && o != attack) dfs(o);
}
int main()
{
int vs, es, query;
scanf("%d%d%d", &vs, &es, &query);
while(es--)
{
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);//無向圖建圖
G[v].push_back(u);
}
while(query--)
{
int x;
scanf("%d", &x);
attack = x;
//計算聯通分量
memset(vis, 0, sizeof(vis));
int scc = 0;
for(int i = 1; i <= vs; i++)
{
if(i == attack || vis[i]) continue;//如果已經被攻佔,或者已經被dfs過了,跳過
dfs(i);
scc++;
}
printf("%d\n", scc - 1);
}
return 0;
}
1014 Waiting in Line (30)(挺繁瑣的模擬)
n個視窗,每個視窗可以排m人。有k位顧客需要辦理業務,給出了每個客戶的辦理業務時間。銀行在8點開始服務,如果視窗都排滿了,客戶就得在黃線外等候。如果有一個視窗使用者服務結束,黃線外的客戶就進來一個。如果有多個可選,選視窗id最小的。輸出查詢客戶的服務結束時間。
1015 Reversible Primes (20)
給定兩個數N,D。如若N是素數,並且N在D進位制下翻轉,並轉化成10進位制還是素數,那麼輸出YES
進位制轉換+質數判斷
1016 Phone Bills (25)(繁瑣的模擬)
n個人的通話記錄,然後給你每個時間段的話費單價,讓你求出每個使用者每個月的電話賬單
1017 Queueing at Bank (25)(繁瑣的模擬)
有n個客戶和k個視窗,給出n個客戶的到達時間和需要的時長。有空閒的視窗就去辦理,沒有的話就需要等待,求客戶的平均時長。如果在8點前來的,就需要等到8點。如果17點以後來的,則不會被服務,無需考慮。
1018 Public Bike Management (30)
給一張圖, 每個節點都代表一個杭州的一個借或者還自行車站點, 節點上的值表示當前這個站點擁有多少輛自行車, 每條邊表示兩個站點之間要花多少時間從一個站點到另一個站點, 給定一個有問題的站點, 求出從控制中心到該站點的最短路徑並且使得帶出去以及拿回來的自行車的數量最少.、
1019 General Palindromic Number (20)
求數N在b進位制下其序列是否為迴文串,並輸出其在b進位制下的表示。
進位制轉換
1020 Tree Traversals (25)
樹的遍歷序列轉換。給出二叉樹的後序遍歷和中序遍歷,求層次遍歷。
遞迴建樹。大白書經典題。
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 500 +5;
typedef pair<int, int>pii;
int post[35], in[35], lch[35], rch[35];
int build(int L1, int R1, int L2, int R2)//in中序遍歷 [L1,R1], post後序遍歷[L2,R2]
{
if(L1 > R1) return -1;
int root = post[R2];
int p = L1;
while(in[p] != root) p++;//推算出根節點在中序遍歷中的位置。
int cnt = p - L1;
lch[root] = build(L1, p - 1, L2, L2 + cnt - 1);//建立左子樹
rch[root] = build(p + 1, R1, L2 + cnt, R2 - 1);//建立右子樹
return root;
}
void level_order(int root)//層序遍歷
{
queue<int>que;
que.push(root);
while(que.size())
{
int cur = que.front();que.pop();
int lson = lch[cur], rson = rch[cur];
if(lson != -1) que.push(lson);
if(rson != -1) que.push(rson);
printf("%d%c", cur, que.size() ? ' ' : '\n');
}
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &post[i]);
for (int i = 0; i < n; i++) scanf("%d", &in[i]);
int root = build(0, n - 1, 0, n - 1);
level_order(root);
return 0;
}
1021 Deepest Root (25)
給出n個點和n-1條邊。若是隻有一個連通分量,且為無環圖,則可將其看成一棵樹,求擁有最大深度的樹的所有根,並按字典序升序輸出。否則輸出連通塊的數目。
這是比前兩個dfs稍微難一點的dfs。其實就是樹的直徑問題,求解樹的直徑,我們是使用dfs的方式,我們先從任意一個點dfs,找到深度最深的點,在開始dfs,找到深度最深的點,這個時候深度就是樹的直徑了。
dfs_scc就是找聯通分塊的函式,其實就是1013的翻版。
dfs_level就是用temp陣列來儲存深度最深的節點有哪些。然後挑任意一個點開始第二次dfs_level,temp陣列即為答案。
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 10000 +5;
int maxLevel;
int vis[maxn];
int level[maxn];
vector<int>G[maxn];
vector<int>temp;
void dfs_scc(int cur)
{
vis[cur] = 1;
for(auto o : G[cur]) if(vis[o] == 0) dfs_scc(o);
}
void dfs_level(int cur, int pa, int lv)
{//深搜層數
level[cur] = lv;
if(lv > maxLevel)
{
maxLevel = lv;
temp.clear();
temp.push_back(cur);
}
else if(lv == maxLevel)
{
temp.push_back(cur);
}
for(auto o : G[cur])
{
if(o != pa)
{
dfs_level(o, cur, lv + 1);
}
}
}
int main()
{
int vs;
scanf("%d", &vs);
for(int i = 1; i < vs; i++)
{
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);//無向圖建圖10
G[v].push_back(u);
}
int scc = 0;
for(int i = 1; i <= vs; i++)
{
if(vis[i] == 0) dfs_scc(i), scc++;
}
if(scc != 1)
{
printf("Error: %d components\n", scc);
}
else
{
set<int>ans;
//第一次dfs
maxLevel = 0;
temp.clear();
memset(level, 0, sizeof(level));
dfs_level(1, -1, 0);
int root = temp[0];
for(auto o : temp) ans.insert(o);
//第二次dfs
maxLevel = 0;
temp.clear();
memset(level, 0, sizeof(level));
dfs_level(root, -1, 0);
root = temp[0];
for(auto o : temp) ans.insert(o);
for(auto o : ans)
{
printf("%d\n", o);
}
}
return 0;
}
1022 Digital Library (30)(繁瑣的模擬)
1023 Have Fun with Numbers (20)
將給出的一個大數*2,判斷其是否可由原來的數通過排列得到。
大數乘法的簡略版。
1024 Palindromic Number (25)
給出一個<=10^10的數,每次將其顛倒後與原數相加,若結果為迴文數,則輸出對應的數和顛倒的次數。
大數加法
1025 PAT Ranking (25)(模擬模擬)
有若干子測試,每個子測試中有ki個人,給出其編號和成績。現在需要你給出最終的成績排名,給出每個人的編號、最終排名、子測試序號、子測試排名。
1026 Table Tennis (30)(挺繁瑣的模擬)
有k個檯球桌,其中有m個為VIP桌。該檯球室營業時間為9:00:00到21:00:00。有若干pair來該檯球室打球。如果檯球桌已滿人,否則使用編號最小的檯球桌。這些人當中有VIP使用者。如果在等待時有個檯球桌剛好空出來,且為VIP桌,則VIP使用者可率先使用,有多個VIP使用者時按到達時間的順序使用。給出該檯球室按每個桌子的開始服務時間排序的使用情況(所服務pair的到來時間、開始服務時間、等待時間),並給出每個桌子服務pair數目。
1027 Colors in Mars (20)
題意:把給出的3個十進位制數轉為3個2為13進位制數。
進位制轉換
1028 List Sorting (25)
給出一些學生的ID、姓名、等級,按照某一列排序並輸出結果。
簡單模擬排序即可
1029 Median (25)
給兩個遞增數列,找出合併以後非遞減排序狀態下的中位數
簡單題。
1030 Travel Plan (30)
給定有權無向圖,找出起點到終點權值最小的最短路。
1031 Hello World for U (20)
給一個字串,輸出一個最接近正方形的U形串
簡單模擬。
1032 Sharing (25)
給定兩個單詞,它們的字母按照連結串列形式相連並給出地址,找出它們開始重合的那個節點的地址。
連結串列。用map模擬一下就好。
1033 To Fill or Not to Fill (25)
1034 Head of a Gang (30)
給定一系列的帶權連通圖,要求其中總權值超過K,節點大於3的圖的個數以及其中該子圖中權值最大的節點。
1035 Password (20)
給定一些賬號和密碼,改掉密碼中的一些特定字元,並按要求輸出
簡單模擬。
1036 Boys vs Girls (25)
給定一些人物資訊,要找到男生成績最差和女生成績最好,並求這兩者差距
簡單模擬
1037 Magic Coupon (25)
給你兩組數,每組拿出一個數,兩兩相乘直到全部用完,求最大的結果是多少。
1038 Recover the Smallest Number (30)
給你n個數字串,問你能組成的最小數是多少,前導0不算
1039 Course List for Student (25)
有n名學生和k門課程,給出每門課程的編號和選修這門課程的人數以及名字,求每名學生選修的課程數以及課程編號。
簡單模擬。
1040 Longest Symmetric String (25)
求最長對稱字串的長度。串的長度只有1000
經典dp。
1041 Be Unique (20)
給你n個數,求出第一個只出現了一次的數。
1042 Shuffling Machine (20)
一副撲克,本來是按順序擺放的,從1-54,給你k,代表要洗牌k次,給你54個數,代表每次洗牌要把i位置的牌洗到a[i]位置,求洗牌k次後這副牌的順序。
簡單模擬。
1043 Is It a Binary Search Tree (25)
讓你判斷一下這棵樹是否是BST。
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1000 +5;
typedef pair<int, int>pii;
struct node
{
int val;
node *left, *right;
node():left(NULL), right(NULL){}
};
int pre[maxn];//二叉搜尋樹的先序序列
bool judge(int L, int R, int k)
{
if(L >= R) return true;
int p = L + 1;
if(k == 0)
{
while(p <= R && pre[p] < pre[L]) p++;//左子樹小於根節點
for(int i = p; i <= R; i++)
{
if(pre[i] < pre[L]) return false;
}
}
else if(k == 1)//BST的映象
{
while(p <= R && pre[p] >= pre[L]) p++;
for(int i = p; i <= R; i++)
{
if(pre[i] >= pre[L]) return false;
}
}
return judge(L + 1, p - 1, k) && judge(p, R, k);
}
node *build(int L, int R, int k)
{
if(L > R) return NULL;
node *root = new node();
root->val = pre[L];
int p = L + 1;
if(k == 0)
{
while(p <= R && pre[p] < pre[L]) p++;//左子樹小於根節點
}
else if(k == 1)//BST的映象
{
while(p <= R && pre[p] >= pre[L]) p++;
}
root->left = build(L + 1, p - 1, k);
root->right = build(p, R, k);
return root;
}
void post_order(node *x, node *root)
{
if(x->left != NULL) post_order(x->left, root);
if(x->right != NULL) post_order(x->right, root);
printf("%d", x->val);
if(x != root) printf(" ");
else printf("\n");
}
void solve(int n)
{
if (judge(0, n - 1, 0))
{
puts("YES");
node *root = build(0, n - 1, 0);
post_order(root, root);
return ;
}
if (judge(0, n - 1, 1))
{
puts("YES");
node *root = build(0, n - 1, 1);
post_order(root, root);
return ;
}
puts("NO");
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &pre[i]);
}
solve(n);
return 0;
}
1044 Shopping in Mars (25)
火星人購物使用鑽石鏈,每顆鑽石都有一定的價值。付款是,要求從鑽石鏈上找到所有剛好能匹配到商品價值的連續的鑽石子鏈,如果沒有, 則找到超過商品價值的最小的鑽石子鏈。
1045 Favorite Color Stripe (30)
最長公共子序列變形