2018年湘潭大学程序设计竞赛 ABCDEFGH

A 时间统计

题目描述

某个实验需要统计时间,记录了实验开始和结束的时间,计算实验用了多少秒。 

输入描述:

第一行输入一个整数n,表示样例个数。接下来每组样例两行,表示开始时间和结束时间,格式为xdayHH:MM:SS,x是一个整数表示第几天,0 < x < 20000,HH表示小时,MM表示分钟,SS表示秒,保证时间合法,结束时间比开始时间晚。

输出描述:

每组数据输出一行一个整数,表示经过的秒数。
示例1

输入

2
1day03:26:12
1day04:26:12
123day15:00:01
19999day15:00:00

输出

3600
1717286399

简单题
 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 
 5 int main() {
 6     int t;
 7     cin >> t;
 8     while(t--) {
 9         ll d1, d2, h1, h2, m1, m2, s1, s2;
10         scanf("%lldday%lld:%lld:%lld",&d1,&h1,&m1,&s1);
11         scanf("%lldday%lld:%lld:%lld",&d2,&h2,&m2,&s2);
12         printf("%lld
",(s2-s1)+(m2-m1)*60+(h2-h1)*3600+(d2-d1)*86400);
13     }
14     return 0;
15 }

 B String

题目描述

有一个只包含大写字母和数字的字符串S,和一个6*6的字符组成的正方形如下图,正方形中恰好包含0-9和A-Z各一个字符。正方形的一行在字符串S中的出现次数是这行6个字符在S中出现次数的总和,正方形的一列在字符串S中的出现次数是这列6个字符在S中出现次数的总和。如果正方形中一个字符所在行的出现次数是所有行中最多,并且所在列的出现次数是所有列中最多,这个字符是需要被找出的。
012345
6789AB
CDEFGH
IJKLMN
OPQRST
UVWXYZ

输入描述:

第一行是一个整数T(1 ≤ T ≤ 400),表示样例的个数。
每个样例一行字符串S,长度1≤ len ≤ 500。

输出描述:

每组数据输出一行需要找出的所有字符,如果需要找出的字符有多个,所在行不同的按行从小到大排序,所在行相同的按列从小到大排序。
示例1

输入

3
13579
AADD
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ

输出

13
7ADG
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ

简单模拟题
 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 char str[10][10] = {"012345","6789AB","CDEFGH",
 5                 "IJKLMN","OPQRST","UVWXYZ"};
 6 char str1[550];
 7 int ans1[10],ans2[10];
 8 int main() {
 9     int t;
10     cin >> t;
11     while(t--) {
12         cin >> str1;
13         int MAX = 0;
14         for(int i = 0; str1[i]; i ++) {
15             for(int j = 0; j < 6; j ++) {
16                 for(int k = 0; k < 6; k ++) {
17                     if(str[j][k] == str1[i]) {
18                         ans1[j]++;
19                         ans2[k]++;
20                     }
21                 }
22             }
23         }
24         for(int i = 0; i < 6; i ++) {
25             for(int j = 0; j < 6; j ++) {
26                 MAX = max(MAX,ans1[i]+ans2[j]);
27             }
28         }
29         for(int i = 0; i < 6; i ++) {
30             for(int j = 0; j < 6; j ++) {
31                 if(ans1[i]+ans2[j] == MAX)
32                     cout << str[i][j];
33             }
34         }
35         cout << endl;
36         memset(ans1,0,sizeof(ans1));
37         memset(ans2,0,sizeof(ans2));
38         memset(str1,0,sizeof(str1));
39     }
40     return 0;
41 }

C Boom

题目描述

紧急事件!战场内被敌军埋放了n枚炸弹!
我军情报部门通过技术手段,掌握了这些炸弹的信息。这些炸弹很特殊,每枚炸弹的波及区域是一个矩形。第i枚炸弹的波及区域是以点(xi1,yi1)为左下角,点(xi2,yi2)为右上角的矩形。
mostshy,作为我军的指挥官,想要知道,如果这些弹同时被敌军引爆,最多将有多少枚炸弹会波及到同一个区域(不考虑边界和角落)。

输入描述:

第一行是一个整数T(1 ≤ T ≤ 50),表示样例的个数。
以后每个样例第一行是一个整数n(1 ≤ n ≤ 50),表示炸弹的个数。
接下来n行,每行四个整数,第i行为x
i1
,y
i1
,x
i2
,y
i2
(0 ≤ x
i1
,y
i1
,x
i2
,y
i2
≤ 100),输入保证合法。

输出描述:

每个样例输出一行,一个整数,表示最多将有多少枚炸弹会波及到同一个区域。
示例1

输入

1
2
0 0 50 50
40 40 100 100

输出

2

说明

在左下角为(40,40),右上角为(50,50)的矩形区域内,有两个炸弹同时波及,所以答案为2。


有个坑,不能等于右上角点。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int ans[110][110];
 4 int main() {
 5     int t, n;
 6     cin >> t;
 7     while (t--) {
 8         cin >> n;
 9         int MAX = 0;
10         while(n--) {
11             int a,b,c,d;
12             cin >> a >> b >> c >> d;
13             for(int i = a; i < c; i ++) {
14                 for(int j = b; j < d; j ++) {
15                     ans[i][j] ++;
16                     MAX = max(MAX,ans[i][j]);
17                 }
18             }
19         }
20         cout << MAX << endl;
21         memset(ans, 0, sizeof(ans));
22     }
23     return 0;
24 }

D Fibonacci进制

题目描述

Fibonacci数是非常有名的一个数列,它的公式为 f(n)=f(n-1)+f(n-2),f(0)=1,f(1)=2。 
我们可以把任意一个数x表示成若干不相同的Fibonacci数的和, 比如说14 = 13+1 = 8+5+1 = 8+3+2+1。
如果把Fibonacci数列作为数的位权,即f(i)作为第i位的位权,每位的系数只能是0或者1,从而得到一个01串。 比如14可以表示成 100001,11001,10111。 我们再把这个01串看成2进制,再转成10进制以后就变成了 33,25,23。 为了避免歧义,我们将使用最小的那个值23。
 请按照这个过程计算一下10进制整数通过上述转换过程得到的10进制整数。

输入描述:

第一行是一个整数T(1 ≤ T ≤ 10000),表示样例的个数。
以后每行一个样例,为一个十进制正整数x(1 ≤ x ≤ 109)。

输出描述:

每行输出一个样例的结果。
示例1

输入

5
1
10
100
1000
1000000000

输出

1
14
367
10966
4083305275263


任何数都可以用斐波拉系数表示,先找到一组可以用斐波拉系数表示的,由于f[i] = f[i-1] + f[i-2] 所以,如果用了第i个斐波拉系数没i-1 i-2没有用,那就换成后者
 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N = 110;
 5 ll f[N], x;
 6 bool vis[N];
 7 map<ll,int> mp;
 8 void dfs(int id) {
 9     if(id < 2) return ;
10     if(!vis[id-1] && !vis[id-2]) {
11         vis[id-1] = vis[id-2] = true;
12         vis[id] = false;
13         dfs(id-2);
14     }
15 }
16 int main() {
17     f[0] = 1;f[1] = 2;//43 1134903170
18     mp[1] = 0; mp[2] = 1;
19     for(int i = 2; i <55; i ++) {
20         f[i] = f[i-1] + f[i-2];
21         mp[f[i]] = i;
22     }
23     int t;
24     cin >> t;
25     while(t--) {
26         memset(vis, 0, sizeof(vis));
27         cin >> x;
28         while(x) {
29             if(mp[x] || x == 1) {
30                 vis[mp[x]] = 1;
31                 x = 0;
32                 break;
33             }
34             int id = upper_bound(f,f+50,x/2)-f;
35             vis[id] = 1;
36             x -= f[id];
37         }
38         for(int i = 2; i < N; i ++) {
39             if(vis[i]) dfs(i);
40         }
41         for(int i = 0; i < 50; i ++) {
42             if(vis[i]) {
43                 x += (1LL<<i);
44             }
45         }
46         cout << x << endl;
47     }
48     return 0;
49 }

E 吃货

题目描述

作为一个标准的吃货,mostshy又打算去联建商业街觅食了。
混迹于商业街已久,mostshy已经知道了商业街的所有美食与其价格,而且他给每种美食都赋予了一个美味度,美味度越高表示他越喜爱这种美食。
mostshy想知道,假如带t元去商业街,只能吃一种食物,能够品味到的美食的美味度最高是多少?

输入描述:

第一行是一个整数T(1 ≤ T ≤ 10),表示样例的个数。
以后每个样例第一行是两个整数n,m(1 ≤ n,m ≤ 30000),表示美食的种类数与查询的次数。
接下来n行,每行两个整数分别表示第i种美食的价格与美味度di,ci(1 ≤ di,ci ≤ 109)。
接下来m行,每行一个整数表示mostshy带t(1 ≤ t ≤ 1e9)元去商业街觅食。

输出描述:

每个查询输出一行,一个整数,表示带t元去商业街能够品味到美食的最高美味度是多少,如果不存在这样的美食,输出0。
示例1

输入

1
3 3
1 100
10 1000
1000000000 1001
9
10
1000000000

输出

100
1000
1001

说明

大量的输入输出,请使用C风格的输入输出。


当10元可以得到1000,而100元得到100时,换成100得到1000,这样在用二分查找最接近t元可以获得多少美味值就行
 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N = 30010;
 5 struct Nod{
 6     int d, c;
 7 }nod[N];
 8 int MAX[N];
 9 bool cmp(Nod &a, Nod &b) {
10     if(a.d != b.d) return a.d < b.d;
11     else return a.c > b.c;
12 }
13 int main() {
14     int t;
15     scanf("%d",&t);
16     while(t--) {
17         int n, m;
18         scanf("%d%d",&n,&m);
19         for(int i = 1; i <= n; i ++) cin >> nod[i].d >> nod[i].c;
20         sort(nod+1,nod+1+n,cmp);
21         for(int i = 1; i <= n; i ++) {
22             MAX[i] = max(MAX[i-1],nod[i].c);
23             // cout << MAX[i] << ' ' ;
24         }
25         // cout <<endl;
26         while(m--) {
27             int x, ans = 0;
28             scanf("%d",&x);
29             int l = 1, r = n;
30             while(l <= r) {
31                 int m = (l+r)>>1;
32                 if(x >= nod[m].d) {
33                     ans = MAX[m];
34                     l = m+1;
35                 } else r = m-1;
36             }
37             printf("%d
",ans);
38             // cout << ans << endl;
39         }
40     }
41     return 0;
42 }

F maze

题目描述

小明来到一个由n x m个格子组成的迷宫,有些格子是陷阱,用'#'表示,小明进入陷阱就会死亡,'.'表示没有陷阱。小明所在的位置用'S'表示,目的地用'T'表示。

小明只能向上下左右相邻的格子移动,每移动一次花费1秒。

有q个单向传送阵,每个传送阵各有一个入口和一个出口,入口和出口都在迷宫的格子里,当走到或被传送到一个有传送阵入口的格子时,小明可以选择是否开启传送阵。如果开启传送阵,小明就会被传送到出口对应的格子里,这个过程会花费3秒;如果不开启传送阵,将不会发生任何事情,小明可以继续向上下左右四个方向移动。

一个格子可能既有多个入口,又有多个出口,小明可以选择任意一个入口开启传送阵。使用传送阵是非常危险的,因为有的传送阵的出口在陷阱里,如果小明使用这样的传送阵,那他就会死亡。也有一些传送阵的入口在陷阱里,这样的传送阵是没有用的,因为小明不能活着进入。请告诉小明活着到达目的地的最短时间。

输入描述:

有多组数据。对于每组数据:
第一行有三个整数n,m,q(2≤ n,m≤300,0≤ q ≤ 1000)。
接下来是一个n行m列的矩阵,表示迷宫。
最后q行,每行四个整数x1,y1,x2,y2(0≤ x1,x2< n,0≤ y1,y2< m),表示一个传送阵的入口在x1行y1列,出口在x2行y2列。

输出描述:

如果小明能够活着到达目的地,则输出最短时间,否则输出-1。
示例1

输入

5 5 1
..S..
.....
.###.
.....
..T..
1 2 3 3
5 5 1
..S..
.....
.###.
.....
..T..
3 3 1 2
5 5 1
S.#..
..#..
###..
.....
....T
0 1 0 2
4 4 2
S#.T
.#.#
.#.#
.#.#
0 0 0 3
2 0 2 2

输出

6
8
-1
3


bfs问题,多了传送,用二维数组存储传送位置,先上下左右,在用传送,取最小值。
 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N = 330;
 5 char str[N][N];
 6 typedef pair<int,int> P;
 7 std::vector<P> v[N][N];
 8 int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
 9 int sx, sy, tx, ty, n, m, q;
10 int d[N][N];
11 void bfs() {
12     queue<P> que;
13     memset(d, -1, sizeof(d));
14     que.push(P(sx,sy));
15     d[sx][sy] = 0;
16     while(que.size()) {
17         P p = que.front(); que.pop();
18         for(int i = 0; i < 4; i ++) {
19             int nx = dx[i] + p.first, ny = dy[i] + p.second;
20             if(0 <= nx && nx < n && 0 <= ny && ny < m && str[nx][ny] != '#') {
21                 if(d[nx][ny] == -1 || d[nx][ny] > d[p.first][p.second] + 1) {
22                     que.push(P(nx,ny));
23                     d[nx][ny] = d[p.first][p.second] + 1;
24                 }
25             }
26         }
27         for(int i = 0; i < v[p.first][p.second].size(); i ++) {
28             int nx = v[p.first][p.second][i].first;
29             int ny = v[p.first][p.second][i].second;
30             if(0 <= nx && nx < n && 0 <= ny && ny < m && str[nx][ny] != '#') {
31                 if(d[nx][ny] == -1 || d[nx][ny] > d[p.first][p.second] + 1) {
32                     que.push(P(nx,ny));
33                     d[nx][ny] = d[p.first][p.second] + 3;
34                 }
35             }
36         }
37     }
38 }
39 void init() {
40     memset(str,0,sizeof(str));
41     for(int i = 0; i < N; i ++) {
42         for(int j = 0; j < N; j ++) {
43             v[i][j].clear();
44         }
45     }
46 }
47 int main() {
48     while(cin >> n >> m >> q) {
49         for(int i = 0; i < n; i ++) cin >> str[i];
50         for(int i = 1; i <= q; i ++) {
51             int x1, x2, y1, y2;
52             cin >> x1 >> y1 >> x2 >> y2;
53             v[x1][y1].push_back(P(x2,y2));
54         }
55         for(int i = 0; i < n; i ++) {
56             for(int j = 0; j < m; j ++) {
57                 if(str[i][j] == 'S') {
58                     sx = i;sy = j;
59                 }else if(str[i][j] == 'T') {
60                     tx = i; ty = j;
61                 }
62             }
63         }
64         bfs();
65         printf("%d
",d[tx][ty]);
66         init();
67     }
68     return 0;
69 }

G又见斐波那契

H 统计颜色

题目描述

n个桶按顺序排列,我们用1~n给桶标号。有两种操作:
1 l r c 区间[l,r]中的每个桶中都放入一个颜色为c的球 (1≤l,r ≤n,l≤r,0≤c≤60)
2 l r   查询区间[l,r]的桶中有多少种不同颜色的球     (1≤l,r ≤n,l≤r)

输入描述:

有多组数据,对于每组数据:
第一行有两个整数n,m(1≤n,m≤100000)
接下来m行,代表m个操作,格式如题目所示。

输出描述:

对于每个2号操作,输出一个整数,表示查询的结果。
示例1

输入

10 10
1 1 2 0
1 3 4 1
2 1 4
1 5 6 2
2 1 6
1 7 8 1
2 3 8
1 8 10 3
2 1 10
2 3 8

输出

2
3
2
4
3


大佬的思路,很巧妙。由于颜色只要60,用数组变成某个颜色的区间,然后查询就可以了。
 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 
 5 struct Nod{
 6     vector<int> l, r;
 7 }nod[66];
 8 
 9 int main() {
10     int n, m;
11     while(scanf("%d%d",&n,&m) != EOF) {
12         for(int i = 0; i <= 60; i ++) {
13             nod[i].l.clear();
14             nod[i].r.clear();
15         }
16         int op, l, r , c;
17         while(m--) {
18             scanf("%d", &op);
19             if(op == 1) {
20                 scanf("%d%d%d",&l,&r,&c);
21                 nod[c].l.push_back(l);
22                 nod[c].r.push_back(r);
23             } else {
24                 scanf("%d%d",&l,&r);
25                 int ans = 0;
26                 for(int i = 0; i <= 60; i ++) {
27                     for(int j = 0; j < nod[i].l.size(); j ++) {
28                         if(nod[i].l[j] <= r && nod[i].r[j] >= l) {
29                             ans++;
30                             break;
31                         }
32                     }
33                 }
34                 cout << ans << endl;
35             }
36         }
37     }
38     return 0;
39 }
原文地址:https://www.cnblogs.com/xingkongyihao/p/8963898.html