【2019湖北省大学程序设计竞赛】网赛

因为已经是大三老狗了,也是正在备考研究生中。。。所以只是申请了号自己打。(连群都不敢进)

感觉今年的题目还算简单的。QAQ。毕竟自己还能做。。(很久没碰真*算法了其实)

而且没有教练给的压力,打的格外开心。

下面就按照我自己做题的顺序来写题解啦。(并不是标程)


E

题意:给你一串数字,对应的是输入法中九键的键盘。n个测试样例的字符串,让你判断可不可能通过这串数字输出。

题解:还是比较简单的模拟。开了个map存对应的数字。然后每个测试字符串对应存一个对应的(数字)字符串,然后对比输入的数字。记得去除大小写和空格。。(我是钻了stl的空子我觉得)

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 map <char,char> mp;
 5 
 6 void init(){
 7     mp['a']='2';mp['b']='2';mp['c']='2';
 8     mp['d']='3';mp['e']='3';mp['f']='3';
 9     mp['g']='4';mp['h']='4';mp['i']='4';
10     mp['j']='5';mp['k']='5';mp['l']='5';
11     mp['m']='6';mp['n']='6';mp['o']='6';
12     mp['p']='7';mp['q']='7';mp['r']='7';mp['s']='7';
13     mp['t']='8';mp['u']='8';mp['v']='8';
14     mp['w']='9';mp['x']='9';mp['y']='9';mp['z']='9';
15 }
16 
17 void trim(string &s){
18     int index = 0;
19     if( !s.empty()){
20         while( (index = s.find(' ',index)) != string::npos){
21             s.erase(index,1);
22         }
23     }
24 
25 }
26 int main(){
27     init();
28     int T;
29     cin>>T;
30     for(int t = 1; t <= T; t++){
31         string s;
32         cin>>s;
33         int n;
34         cin>>n;
35         printf("Case #%d:\n",t);
36         string ss;
37         getline(cin,ss);
38         while(n--){
39             getline(cin,ss);
40             trim(ss);
41             transform(ss.begin(),ss.end(),ss.begin(),::tolower);
42             string res;
43             for(int i = 0; i < ss.size();i++){
44                 //cout<<mp[ss[i]]<<endl;
45                 res += mp[ss[i]];
46             }
47             if(res == s)    cout<<"Maybe.."<<endl;
48             else    cout<<"How could that be possible?"<<endl;
49         }
50 
51     }
52     return 0;
53 }
View Code

B

题意:一个喝醉的小仓鼠,沿着上右下左的顺序走,问你n次后离原点的距离的平方是多少。

题解:也是个简单模拟。把原点当作(0,0),上下左右也就是对xy+-.(记得long long)。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 
 5 int main(){
 6     int T;
 7     cin>>T;
 8     for(int t = 1; t <= T; t++){
 9         int n;
10         cin>>n;
11         int x=0,y=0;
12         int xx;
13 
14         for(int i = 0; i < n ;i++){
15             cin>>xx;
16             if(i%4 == 0) y += xx;    
17             else if(i%4 == 1)    x += xx;
18             else if(i%4 == 2)    y -= xx;
19             else if(i%4 == 3)    x -= xx;
20         }
21         ll dis = x*x + y*y;
22         printf("Case #%d:%I64d\n",t,dis);
23     }
24 
25     return 0;
26 }
View Code

F

题意:有n座山,给你n座山的高度,n-1条路。m次询问。u和v之间经过的山第k高是哪一座。

题解:一个主席树+LCA的静态区间查询第k小的模板题。。板子上是第k大,所以要改一下变成第k小。

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 const int maxN = 1e5 + 7;
  5 
  6 int N, M, a[maxN], b[maxN], diff, root[maxN][20], deep[maxN], cnt, head[maxN];
  7 int order, tree[maxN], lson[maxN*20], rson[maxN*20], siz[maxN*20];
  8 
  9 struct Eddge{
 10     int nex, to;
 11     Eddge(int a=-1, int b=0):nex(a), to(b) {}
 12 }edge[maxN<<1];
 13 
 14 void addEddge(int u, int v){
 15     edge[cnt] = Eddge(head[u], v);
 16     head[u] = cnt++;
 17 }
 18 
 19 void dfs(int u, int pre, int depth){
 20     root[u][0] = pre;
 21     deep[u] = depth;
 22     for(int i=head[u]; i!=-1; i=edge[i].nex){
 23         int v = edge[i].to;
 24         if(v == pre) continue;
 25         dfs(v, u, depth + 1);
 26     }
 27 }
 28 
 29 void pre_LCA(){
 30     dfs(1, 0, 0);
 31     for(int j=0; (1<<(j+1))<N ; j++){
 32         for(int i=1; i<=N; i++){
 33             if(root[i][j] < 0) root[i][j+1] = -1;
 34             else root[i][j+1] = root[root[i][j]][j];
 35         }
 36     }
 37 }
 38 
 39 int get_LCA(int x, int y){
 40     if(deep[x] < deep[y]) swap(x, y);
 41     int det = deep[x] - deep[y];
 42     for(int i=0; (1<<i)<=det; i++) if( (det>>i) & 1 ) x = root[x][i];
 43     if(x == y) return x;
 44     for(int i = log2(1. * N); i>=0; i--){
 45         if(root[x][i] != root[y][i]){
 46             x = root[x][i];
 47             y = root[y][i];
 48         }
 49     }
 50     return root[x][0];
 51 }
 52 
 53 void build(int &k, int l, int r){
 54     k = ++order;
 55     siz[k] = 0;
 56     if(l == r) return;
 57     int mid = (l + r)>>1;
 58     build(lson[k], l, mid);
 59     build(rson[k], mid + 1, r);
 60 }
 61 
 62 void update(int old, int &now, int l, int r, int qx){
 63     now = ++order;
 64     lson[now] = lson[old]; rson[now] = rson[old];   siz[now] = siz[old] + 1;
 65     if(l == r) return;
 66     int mid = (l + r)>>1;
 67     if(qx <= mid) update(lson[old], lson[now], l, mid, qx);
 68     else update(rson[old], rson[now], mid + 1, r, qx);
 69 }
 70 
 71 int query(int i, int j, int l, int r, int k, int lca, int fsa){
 72     if(l == r) return l;
 73     int det = siz[lson[i]] + siz[lson[j]] - siz[lson[lca]] - siz[lson[fsa]];
 74     int mid = (l + r)>>1;
 75     if(k <= det) return query(lson[i], lson[j], l, mid, k, lson[lca], lson[fsa]);
 76     else return query(rson[i], rson[j], mid + 1, r, k - det, rson[lca], rson[fsa]);
 77 }
 78 
 79 void dfs_build(int u, int pre){
 80     int pos = (int)(lower_bound(b + 1, b + diff + 1, a[u]) - b);
 81     update(tree[pre], tree[u], 1, diff, pos);
 82     for(int i=head[u]; i!=-1; i=edge[i].nex){
 83         int v = edge[i].to;
 84         if(v == pre) continue;
 85         dfs_build(v, u);
 86     }
 87 }
 88 
 89 void init(){
 90     memset(head, -1, sizeof(head));
 91     cnt = order = 0;
 92     memset(root, -1, sizeof(root));
 93 }
 94 
 95 int main(){   
 96     int T;
 97     cin>>T;
 98     while(T--){
 99         scanf("%d%d", &N, &M);
100         init();
101         for(int i=1; i<=N; i++){
102             scanf("%d", &a[i]);
103             b[i] = a[i];
104         }
105 
106         sort(b + 1, b + N + 1);
107         diff = (int)(unique(b + 1, b + N + 1) - b - 1);
108         for(int i=1; i<N; i++){
109             int e1, e2; scanf("%d%d", &e1, &e2);
110             addEddge(e1, e2);
111             addEddge(e2, e1);
112         }
113         pre_LCA();
114         build(tree[0], 1, diff);
115         dfs_build(1, 0);
116         for(int i=1; i<=M; i++){
117             int l, r, op;    scanf("%d%d%d", &l, &r, &op);
118             int lca = get_LCA(l, r);
119             //第k大变成第k小
120             op = deep[l] + deep[r] - 2 * deep[lca] - op + 2;
121             if(op<=0) printf("-1\n");
122             else
123                 printf("%d\n", b[query(tree[l], tree[r], 1, diff, op, tree[lca], tree[root[lca][0]])]);
124         }
125     }
126     return 0;
127 }
View Code

D

题意:蒲公英的种子最开始在点(0,0),没风的时候上走,有风的时候向右走。它要到(m,n)请问有多少种走法。

题解:经典。组合数问题啊。QAQ我记得我区预赛卡死在组合数上了。公式:C(n+m-1,m) -  C(n+m-1,m-1)。记得取模。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn = 500005, MOD = 1e9 + 7;
 5 int F[maxn], Finv[maxn], inv[maxn];//F是阶乘,Finv是逆元的阶乘 
 6 void init(){
 7     inv[1] = 1;
 8     for(int i = 2; i < maxn; i ++){
 9         inv[i] = (MOD - MOD / i) * 1ll * inv[MOD % i] % MOD;
10     }
11     F[0] = Finv[0] = 1;
12     for(int i = 1; i < maxn; i ++){
13         F[i] = F[i-1] * 1ll * i % MOD;
14         Finv[i] = Finv[i-1] * 1ll * inv[i] % MOD;
15     }
16 }
17 int comb(int n, int m){
18     if(m < 0 || m > n) return 0;
19     return F[n] * 1ll * Finv[n - m] % MOD * Finv[m] % MOD;
20 }
21 
22 int main() {
23     init();
24     int n, m;
25     int t;
26     scanf("%d",&t);
27     while (t--) {
28         scanf("%d%d", &m, &n);
29         printf("%d\n", (comb(n + m - 1, m) - comb(n + m - 1, m - 1) + MOD) % MOD);
30     }
31     return 0;
32 }
View Code

A(计算几何)和C(线段树)我一时没有想到什么好的办法。打算看了标程再补一下题。。QAQ。

猜你喜欢

转载自www.cnblogs.com/Asumi/p/10667385.html