PAT团体程序设计天梯赛 - 模拟赛

由于本人愚笨,最后一题实在无力AC,于是只有前14题的题解Orz

总的来说,这次模拟赛的题目不算难,前14题基本上一眼就有思路,但是某些题写起来确实不太容易,编码复杂度有点高~

L1-1 N个数求和

设计一个分数类,重载加法运算符,注意要约分,用欧几里得算法求个最大公约数即可。

 1 #include <cstdio>
 2 
 3 long long abs(long long x)
 4 {
 5     return x < 0 ? -x : x;
 6 }
 7 
 8 long long gcd(long long a, long long b)
 9 {
10     if (b == 0)
11         return a;
12     else if (a > b)
13         return gcd(b, a % b);
14     else
15         return gcd(a, b % a);
16 }
17 
18 struct FS
19 {
20     long long fz, fm;
21     FS(long long _fz = 0, long long _fm = 1)
22     {
23         fz = _fz;
24         fm = _fm;
25         if (fz & fm)
26         {
27             long long g = gcd(abs(fz), abs(fm));
28             fz /= g;
29             fm /= g;
30         }
31     }
32     friend FS operator+ (const FS& a, const FS& b)
33     {
34         FS ans;
35         long long lcm = a.fm / gcd(abs(a.fm), abs(b.fm)) * b.fm;
36         ans.fz = a.fz * (lcm / a.fm) + b.fz * (lcm / b.fm);
37         ans.fm = lcm;
38         if (ans.fz && ans.fm)
39         {
40             long long g = gcd(abs(ans.fz), abs(ans.fm));
41             ans.fz /= g;
42             ans.fm /= g;
43         }
44         return ans;
45     }
46 };
47 
48 int main()
49 {
50     int n;
51     scanf("%d", &n);
52     FS ans;
53     char buf[64];
54     while (n--)
55     {
56         scanf("%s", buf);
57         long long fz, fm;
58         sscanf(buf, "%lld/%lld", &fz, &fm);
59         ans = ans + FS(fz, fm);
60     }
61     if (ans.fz == 0)
62         printf("0");
63     else if (abs(ans.fz) < abs(ans.fm))
64         printf("%lld/%lld", ans.fz, ans.fm);
65     else
66     {
67         if (ans.fz % ans.fm == 0)
68             printf("%lld", ans.fz / ans.fm);
69         else
70             printf("%lld %lld/%lld", ans.fz / ans.fm, ans.fz % ans.fm, ans.fm);
71     }
72     return 0;
73 }

 


L1-2 比较大小

太水了,不解释,直接sort一下。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int a[3];
 8     scanf("%d%d%d", a, a + 1, a + 2);
 9     sort(a, a + 3);
10     printf("%d->%d->%d", a[0], a[1], a[2]);
11     return 0;
12 }

 


L1-3 A-B

用一个bool数组记录第二个字符串中出现的字符,然后遍历第一个字符串,检测是否在第二个字符串中出现过。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 char s1[10010];
 6 char s2[10010];
 7 bool vis[128];
 8 
 9 int main()
10 {
11     gets(s1);
12     gets(s2);
13     int idx = -1;
14     while (s2[++idx])
15         vis[s2[idx]] = true;
16     idx = -1;
17     while (s1[++idx])
18         if (!vis[s1[idx]])
19             putchar(s1[idx]);
20     return 0;
21 }

 


L1-4 计算指数

太水了,直接左移位。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int n;
 8     scanf("%d", &n);
 9     printf("%d^%d = %d", 2, n, 1 << n);
10     return 0;
11 }

 


L1-5 计算阶乘和

太水了,求阶乘累加。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int n;
 8     scanf("%d", &n);
 9     int sum = 0;
10     int fact = 1;
11     for (int i = 1; i <= n; i++)
12         sum += fact *= i;
13     printf("%d", sum);
14     return 0;
15 }

 


L1-6 简单题

hello world同级别的题。

1 #include <cstdio>
2 int main() 
3 {
4     printf("This is a simple problem.");
5     return 0;
6 }

 


L1-7 跟奥巴马一起画方块

双重循环。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int n;
 8     char c[2];
 9     scanf("%d%s", &n, c);
10     for (int i = 0; i < (n + 1) / 2; i++, puts(""))
11         for (int j = 0; j < n; j++)
12             putchar(c[0]);
13     return 0;
14 }

 


L1-8 查验身份证

按规则模拟就好了,注意判断前17位有无非数字。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int wei[] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
 6 int rlt[] = {1,0,-1,9,8,7,6,5,4,3,2};
 7 
 8 bool check(char *s)
 9 {
10     int sum = 0;
11     for (int i = 0; i < 17; i++)
12     {
13         if (!isdigit(s[i]))
14             return false;
15         sum += (s[i] - '0') * wei[i];
16     }
17     sum %= 11;
18     if (rlt[sum] == -1)
19         return s[17] == 'X';
20     else
21         return s[17] - '0' == rlt[sum];
22 }
23 
24 int main()
25 {
26     int n;
27     char s[20];
28     scanf("%d", &n);
29     bool allpass = true;
30     while (n--)
31     {
32         scanf("%s", s);
33         if (!check(s))
34         {
35             puts(s);
36             allpass = false;
37         }
38     }
39     if (allpass)
40         puts("All passed");
41     return 0;
42 }

 


L2-1 集合相似度

排序后,对于每个询问二分好像会超时一组数据。那么我们可以把那些数字离散化&去重之后,用hash思想来做,O(M)复杂度处理每个查询。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int sorted[500010];
 6 int sset[60][10010];
 7 bool vis[500010];
 8 int rec[20010];
 9 
10 int main()
11 {
12     int n;
13     scanf("%d", &n);
14     int tot = 0;
15     for (int i = 0; i < n; i++)
16     {
17         scanf("%d", &sset[i][0]);
18         for (int j = 1; j <= sset[i][0]; j++)
19             scanf("%d", &sset[i][j]), sorted[tot++] = sset[i][j];
20         sort(sset[i] + 1, sset[i] + 1 + sset[i][0]);
21         sset[i][0] = unique(sset[i] + 1, sset[i] + 1 + sset[i][0]) - sset[i] - 1;
22     }
23     sort(sorted, sorted + tot);
24     tot = unique(sorted, sorted + tot) - sorted;
25     for (int i = 0; i < n; i++)
26         for (int j = 1; j <= sset[i][0]; j++)
27             sset[i][j] = lower_bound(sorted, sorted + tot, sset[i][j]) - sorted;
28     int k;
29     scanf("%d", &k);
30     while (k--)
31     {
32         int a, b;
33         scanf("%d%d", &a, &b);
34         a--, b--;
35         int nc = 0, nt = 0;
36         int reccnt = 0;
37         for (int i = 1; i <= sset[a][0]; i++)
38             vis[sset[a][i]] = true, rec[reccnt++] = sset[a][i];
39         nt = sset[a][0];
40         for (int i = 1; i <= sset[b][0]; i++)
41         {
42             rec[reccnt++] = sset[b][i];
43             if (vis[sset[b][i]])
44                 nc++;
45             else
46                 nt++;
47         }
48         for (int i = 0; i < reccnt; i++)
49             vis[rec[i]] = false;
50         printf("%.2f%\n", 1.0 * nc / nt * 100);
51     }
52     return 0;
53 }

 


L2-2 树的遍历

后序序列最后一个是根节点,用那个根节点把中序序列分开,然后递归建树,最后再宽搜一下。

 1 #include <cstdio>
 2 #include <vector>
 3 #include <queue>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 vector<int> tree[40];
 8 int n;
 9 int hx[40];
10 int zx[40];
11 
12 int deal(int lz, int rz, int lh, int rh)
13 {
14     if (lz > rz || lh > rh)
15         return -1;
16     int root = hx[rh];
17     int pos = find(zx + lz, zx + rz + 1, root) - zx;
18     int cnt = pos - lz;
19     tree[root].push_back(deal(lz, pos - 1, lh, lh + cnt - 1));
20     tree[root].push_back(deal(pos + 1, rz, lh + cnt, rh - 1));
21     return root;
22 }
23 
24 int main()
25 {
26     scanf("%d", &n);
27     for (int i = 0; i < n; i++)
28         scanf("%d", hx + i);
29     for (int i = 0; i < n; i++)
30         scanf("%d", zx + i);
31     int root = deal(0, n - 1, 0, n - 1);
32     queue<int> q;
33     q.push(root);
34     bool flag = false;
35     while (!q.empty())
36     {
37         int cur = q.front();
38         q.pop();
39         if (flag)
40             printf(" %d", cur);
41         else
42             printf("%d", cur), flag = true;
43         if (tree[cur][0] != -1)
44             q.push(tree[cur][0]);
45         if (tree[cur][1] != -1)
46             q.push(tree[cur][1]);
47     }
48     return 0;
49 }

 


L2-3 家庭房产

思路很简单,就是普通的并查集,但是代码不太好写哦~

#include <cstdio>
#include <algorithm>
using namespace std;

struct Node
{
    int parent;
    int ts, mj;
};
struct Result
{
    int minid;
    int siz;
    int ts, mj;
    friend bool operator< (const Result& a, const Result& b)
    {
        if (1LL * a.mj * b.siz == 1LL * b.mj * a.siz)
            return a.minid < b.minid;
        return 1LL * a.mj * b.siz > 1LL * b.mj * a.siz;
    }
};
Node node[10010];
Result rlt[10010];

int uf_find(int x)
{
    if (node[x].parent == x)
        return x;
    return node[x].parent = uf_find(node[x].parent);
}

void uf_union(int x, int y)
{
    x = uf_find(x);
    y = uf_find(y);
    if (x != y)
        node[x].parent = y;
}

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < 10000; i++)
        node[i].parent = i, rlt[i].minid = 1000000;
    while (n--)
    {
        int id, f, m, k, hz;
        scanf("%d%d%d%d", &id, &f, &m, &k);
        if (f != -1)
            uf_union(f, id);
        if (m != -1)
            uf_union(m, id);
        for (int i = 0; i < k; i++)
        {
            scanf("%d", &hz);
            uf_union(hz, id);
        }
        scanf("%d%d", &node[id].ts, &node[id].mj);
    }
    for (int i = 0; i < 10000; i++)
    {
        int x = uf_find(i);
        rlt[x].minid = min(rlt[x].minid, i);
        rlt[x].ts += node[i].ts;
        rlt[x].mj += node[i].mj;
        rlt[x].siz++;
    }
    sort(rlt, rlt + 10000);
    int cnt = 0;
    for (int i = 0; i < 10000; i++)
    {
        if (rlt[i].mj != 0)
            cnt++;
        else
            break;
    }
    printf("%d\n", cnt);
    for (int i = 0; i < cnt; i++)
    {
        if (rlt[i].mj != 0)
            printf("%04d %d %.3f %.3f\n", rlt[i].minid, rlt[i].siz,
                   1.0 * rlt[i].ts / rlt[i].siz, 1.0 * rlt[i].mj / rlt[i].siz);
    }
    return 0;
}

 


L2-4 最长对称子串

枚举回文中点,向两边扩展枚举。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 char s[1010];
 7 
 8 int main()
 9 {
10     gets(s);
11     int len = strlen(s);
12     int ans = 0;
13     for (int i = 0; i < len; i++)
14     {
15         int l = i, r = i;
16         int curans = 0;
17         while (l >= 0 && r < len && s[l] == s[r])
18             curans += 2, l--, r++;
19         ans = max(ans, curans - 1);
20         if (i < len - 1 && s[i] == s[i + 1])
21         {
22             l = i;
23             r = l + 1;
24             curans = 0;
25             while (l >= 0 && r < len && s[l] == s[r])
26                 curans += 2, l--, r++;
27             ans = max(ans, curans);
28         }
29     }
30     printf("%d", ans);
31     return 0;
32 }

 


L3-1 肿瘤诊断

三维的图找连通块,道理和二维一样,注意这里只能宽搜。

 1 #include <cstdio>
 2 #include <queue>
 3 using namespace std;
 4 
 5 bool pic[61][1287][129];
 6 bool vis[61][1287][129];
 7 int dx[] = {1,-1,0,0,0,0};
 8 int dy[] = {0,0,-1,1,0,0};
 9 int dz[] = {0,0,0,0,1,-1};
10 int m, n, l, t;
11 
12 int bfs(int z, int x, int y)
13 {
14     queue<int> q;
15     q.push(z * (m * n) + x * n + y);
16     vis[z][x][y] = true;
17     int cnt = 0;
18     while (!q.empty())
19     {
20         cnt++;
21         int cur = q.front();
22         q.pop();
23         z = cur / (m * n);
24         cur %= m * n;
25         x = cur / n;
26         y = cur % n;
27         for (int i = 0; i < 6; i++)
28         {
29             int zz = z + dz[i];
30             int xx = x + dx[i];
31             int yy = y + dy[i];
32             if (zz < 0 || zz >= l)
33                 continue;
34             if (xx < 0 || xx >= m)
35                 continue;
36             if (yy < 0 || yy >= n)
37                 continue;
38             if (pic[zz][xx][yy] && !vis[zz][xx][yy])
39             {
40                 vis[zz][xx][yy] = true;
41                 q.push(zz * (m * n) + xx * n + yy);
42             }
43         }
44     }
45     return cnt;
46 }
47 
48 int main()
49 {
50     scanf("%d%d%d%d", &m, &n, &l, &t);
51     for (int i = 0; i < l; i++)
52         for (int j = 0; j < m; j++)
53             for (int k = 0; k < n; k++)
54             {
55                 int v;
56                 scanf("%d", &v);
57                 pic[i][j][k] = v == 1;
58             }
59     int ans = 0;
60     for (int i = 0; i < l; i++)
61         for (int j = 0; j < m; j++)
62             for (int k = 0; k < n; k++)
63             {
64                 if (!vis[i][j][k] && pic[i][j][k])
65                 {
66                     int cnt = bfs(i, j, k);
67                     if (cnt >= t)
68                         ans += cnt;
69                 }
70             }
71     printf("%d", ans);
72     return 0;
73 }

 


L3-2 垃圾箱分布

跑m次spfa就好了,注意结果四舍五入~

 1 #include <cstdio>
 2 #include <vector>
 3 #include <queue>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const long long inf = 1LL << 62;
 8 vector<pair<int, int> > G[1020];
 9 long long dis[1020];
10 bool inqueue[1020];
11 int n, m, k;
12 long long ds;
13 long long ansdis = -1;
14 double avgdis = 1e30;
15 int ansid = -1;
16 
17 void spfa(int s)
18 {
19     fill(dis, dis + 1020, inf);
20     queue<int> q;
21     q.push(s);
22     dis[s] = 0;
23     while (!q.empty())
24     {
25         int cur = q.front();
26         q.pop();
27         inqueue[cur] = false;
28         for (int i = 0; i < G[cur].size(); i++)
29         {
30             if (dis[cur] + G[cur][i].second < dis[G[cur][i].first])
31             {
32                 dis[G[cur][i].first] = dis[cur] + G[cur][i].second;
33                 if (!inqueue[G[cur][i].first])
34                 {
35                     inqueue[G[cur][i].first] = true;
36                     q.push(G[cur][i].first);
37                 }
38             }
39         }
40     }
41     long long mindis = *min_element(dis + 1, dis + n + 1);
42     long long maxdis = *max_element(dis + 1, dis + n + 1);
43     if (maxdis > ds)
44         return;
45     double sum = 0.0;
46     for (int i = 1; i <= n; i++)
47         sum += dis[i];
48     sum /= n;
49     if (mindis > ansdis)
50     {
51         ansdis = mindis;
52         avgdis = sum;
53         ansid = s;
54     }
55     else if (mindis == ansdis)
56     {
57         if (avgdis - sum > 1e-9)
58         {
59             ansdis = mindis;
60             avgdis = sum;
61             ansid = s;
62         }
63     }
64 }
65 
66 int main()
67 {
68     scanf("%d%d%d%lld", &n, &m, &k ,&ds);
69     for (int i = 0; i < k; i++)
70     {
71         char s1[10], s2[10];
72         int a, b, d;
73         scanf("%s%s%d", s1, s2, &d);
74         if (s1[0] == 'G')
75             sscanf(s1 + 1, "%d", &a), a += n;
76         else
77             sscanf(s1, "%d", &a);
78         if (s2[0] == 'G')
79             sscanf(s2 + 1, "%d", &b), b += n;
80         else
81             sscanf(s2, "%d", &b);
82         G[a].push_back(make_pair(b, d));
83         G[b].push_back(make_pair(a, d));
84     }
85     for (int i = n + 1; i <= n + m; i++)
86         spfa(i);
87     if (ansid == -1)
88         puts("No Solution");
89     else
90     {
91         avgdis *= 10.0;
92         avgdis += 0.5;
93         avgdis = floor(avgdis);
94         avgdis /= 10.0;
95         printf("G%d\n%.1lf %.1lf", ansid - n, 1.0 * ansdis, avgdis);
96     }
97     return 0;
98 }

 

posted @ 2016-05-17 00:05  iRedBean  阅读(1705)  评论(1编辑  收藏  举报