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\n",(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,作为我军的指挥官,想要知道,如果这些弹同时被敌军引爆,最多将有多少枚炸弹会波及到同一个区域(不考虑边界和角落)。
我军情报部门通过技术手段,掌握了这些炸弹的信息。这些炸弹很特殊,每枚炸弹的波及区域是一个矩形。第i枚炸弹的波及区域是以点(xi1,yi1)为左下角,点(xi2,yi2)为右上角的矩形。
mostshy,作为我军的指挥官,想要知道,如果这些弹同时被敌军引爆,最多将有多少枚炸弹会波及到同一个区域(不考虑边界和角落)。
输入描述:
第一行是一个整数T(1 ≤ T ≤ 50),表示样例的个数。i1
以后每个样例第一行是一个整数n(1 ≤ n ≤ 50),表示炸弹的个数。
接下来n行,每行四个整数,第i行为x
,yi1
,xi2
,yi2
(0 ≤ xi1
,yi1
,xi2
,yi2
≤ 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元去商业街,只能吃一种食物,能够品味到的美食的美味度最高是多少?
混迹于商业街已久,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\n",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\n",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)
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 }