[比赛][ICPC2020] 2020ICPC小米 网络选拔赛第一场

一、前言

听说今年难得有场邀请赛,而且还是在北京线下,感觉是个大好的机会 —— 毕竟上次参加南昌场的邀请赛直接夺银,感觉状态再好点冲个金也没问题。然而事实告诉我这并不是场一如既往的邀请赛,43 个名额实在少得可怜,而且学校似乎并没有名额限制,以至于清北直接屠榜了,不知道是今年情况特殊还是这场比赛特殊。最后勉为其难写了 5 道题,距离入围依旧遥不可及。

 

二、比赛概况

1、比赛链接

https://ac.nowcoder.com/acm/contest/7501

2、题目情况

A 题:数论 + 动态规划

B 题:计算几何 + 最短路

C 题(签到题):模拟;

D 题:图论

E 题:略

F 题:二分答案

G 题:略

H 题:略

I 题:搜索(BFS)+ 图论

J 题:二维前缀和 + 二维差分

K 题:略

3、得分情况

AC 了 A, C, D, I, J 五道,终榜 rank300+。

 

三、题目分析

A. Intelligent Warehouse

1、题目链接

https://ac.nowcoder.com/acm/problem/211807

2、题面

In MI Intelligent Warehouse, there are nn products, where the i-th product is of size aiai. We always need to box producsts into all kinds of containers, and it will be safer and more cost efficient if for any two sizes of products, one is the other's multiple, since there won't be any residual room in one container. So for each boxing we need to choose some products that for any two chosen products, either aiai is multiple of ajaj or ajaj is multiple of aiai. Print the maximum number of products that can be chosen in one boxing.

3、题目大意

给出数列 a,从中选出尽可能多的数,使任意两个数之间存在倍数关系。

4、分析与思路

5、题解

6、代码

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define MAXV 10000010
 5 #define MAXN 200010
 6 
 7 const int maxV = 1e7 + 1;
 8 
 9 int n, a[MAXN], f[MAXV], p[MAXV], s[MAXV], cnt;
10 int pl[MAXN], ql[MAXN], ans, pc;
11 
12 int solve(int d, int r) {
13     if (d < 0) return f[r];
14     int res = 0;
15     for (int i = 0; i <= ql[d]; i++) {
16         res = max(solve(d - 1, r), res);
17         r /= pl[d];
18     }
19     return res;
20 }
21 
22 void work() {
23     p[1] = 1;
24     for (int i = 2; i < maxV; i++) {
25         if (!p[i])
26             p[i] = i, s[cnt++] = i;
27         for (int j = 0; j < cnt && 1ll * i * s[j] < maxV; j++) {
28             p[i * s[j]] = s[j];
29             if (i % s[j] == 0) break;
30         }
31     }
32     sort(a, a + n);
33     for (int i = 0; i < n; i++) {
34         int o = a[i];
35         pc = 0;
36         while (o > 1) {
37             if (pc && pl[pc - 1] == p[o])
38                 ql[pc - 1]++;
39             else    
40                 pl[pc] = p[o], ql[pc] = 1, pc++;
41             o /= p[o];
42         }
43         f[a[i]] = solve(pc - 1, a[i]) + 1;
44         ans = max(f[a[i]], ans);
45     }
46     cout << ans;
47 }
48 
49 int main() {
50     cin >> n;
51     for (int i = 0; i < n; i++)
52         cin >> a[i];
53     work();
54     return 0;
55 }

 

C. Smart Browser

1、题目链接

https://ac.nowcoder.com/acm/problem/211809

2、题面

In some social platforms, there are some netizen who like to post "www". Since the string is like the grass, which contains plenty of "/\" shapes, so there are also some netizen who post "grass".

As a fast, smart, and convenient browser, MI Browser can recognize this kind of text and show some special effects. Specifically, given a string, MI Browser will determine the number of "/\" shapes made by character "w", where "w" itself and the gap between two adjacent "w"s both give one `/\` shape. If still not clear, please turn to sample input/output for more details.

As a MI fan, you want to detect the relationship between the special effects and the number of "/\" shapes, so the thing you should do first is to determine the number of "/\" shapes by yourself.

3、题目大意

给出一个字符串,求出若干个由连续的 w 组成的子串。

4、分析与思路

5、题解

6、代码

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 #define MAXN 100005
 5  
 6 int l, o = 1, tot, ans;
 7 char a[MAXN];
 8  
 9 int main() {
10     cin >> a + 1;
11     l = strlen(a + 1);
12     while (o <= l) {
13         if (a[o] == 'w') {
14             tot = 0;
15             while (a[o] == 'w') o++, tot++;
16             ans += tot * 2 - 1;
17         }  
18         o++;
19     }
20     cout << ans;
21     return 0;
22 }

 

D. Router Mesh 

1、题目链接

https://ac.nowcoder.com/acm/problem/211810

2、题面

In a Mesh networking system, there are nn MI Routers, where mm pairs of MI Routers are bidirectionally connected. In order to check the stability of the system, for each MI Router, we should determine the number of connected components after removing it and relative connections from the system. And then assess that if we should add more MI Routers into the system. Print the numbers of connected components in residual system after removing each MI Router.

3、题目大意

给出由 n 个点,m 条边组成的非连通无向图,求出每次删除其中一个点后的连通块个数。

4、分析与思路

5、题解

6、代码

 1 #include <bits/stdc++.h>
 2  
 3 using namespace std;
 4 typedef long long ll;
 5 typedef unsigned long long ull;
 6 const int N = 3e5 + 50;
 7 const int NN = 2e5 + 50;
 8 const int M = 1e9 + 7;
 9 int n,m;
10 struct Edge{
11     int u,v,nxt,cut;
12 } e[N*2];
13 int cnt = 1, head[N], dfn[N],low[N];
14 int ans[N];
15 int mx = 0;
16 int clk = 0;
17 #define multi_case
18 #undef multi_case
19 void add_edge(int u,int v) {
20     e[++cnt] = (Edge){u,v,head[u],0};
21     head[u] = cnt;
22     e[++cnt] = (Edge){v,u,head[v],0};
23     head[v] = cnt;
24 }
25 void pre() {
26     cin >> n >> m;
27     for(int i = 1; i <= m; i++) {
28         int v,u;
29         cin >> u >> v;
30         add_edge(u,v);
31     }
32 }
33 void Tarjan(int u,int fa) {
34     dfn[u]=low[u]=++clk;
35     ans[u] = 0;
36     int cnt = 0;
37     if(fa == 0) ans[u] = -1;
38     for(int i=head[u];i;i=e[i].nxt) {
39         int v = e[i].v;
40         if(!dfn[v])
41         {
42             cnt++;
43             Tarjan(v,u);
44             low[u]=min(low[v],low[u]);
45             if(fa == 0) {
46                 ans[u] = cnt-1;
47             }
48             else if(fa != 0 && low[v] >= dfn[u])
49                 ans[u]++;
50         }
51         else if(v != fa)
52             low[u]=min(low[u],dfn[v]);
53     }
54 }
55 void solve(int _case) {
56     int block_cnt = 0;
57     for(int i = 1; i <= n; i++) {
58         if(dfn[i] == 0) {
59             Tarjan(i,0);
60             block_cnt++;
61         }
62     }
63     for(int u = 1; u <= n; u++) {
64  
65         printf("%d%c", block_cnt + ans[u], " \n"[u==n]);
66     }
67 }
68 int main() {
69     ios::sync_with_stdio(false);
70     cin.tie(0);
71     int t;
72     pre();
73 #ifdef multi_case
74     cin >> t;
75 #else
76     t = 1;
77 #endif
78     for (int i = 1; i <= t; i++) {
79         solve(i);
80     }
81     return 0;
82 }

(樊总的代码)

 

I. Walking Machine

1、题目链接

https://ac.nowcoder.com/acm/problem/211810

2、题面

链接:https://ac.nowcoder.com/acm/problem/211820
来源:牛客网

Given a maze of size n×mn\times mn×m, where upper left corner is (1,1)(1,1) and lower right corner is (n,m)(n,m). For each cell (x,y)(x,y), there is exactly one character c (c∈{W,A,S,D})c (c{W,A,S,D}) on it, denoting the moving restriction:

* If c=Wc=W, you can only go up from this cell, specifically go from (x,y)(x,y) to (x−1,y)(x1,y)

* If c=A, you can only go left from this cell, specifically go from (x,y) to (x,y−1)(x,y1)

* If c=Sc=S, you can only go down from this cell, specifically go from (x,y)(x,y) to (x+1,y)(x+1,y)

* If c=Dc=D, you can only go right from this cell, specifically go from (x,y)(x,y) to (x,y+1)(x,y+1)

We say one is out if x<1x<1 or x>n or y<1y<1 or y>my>m holds, now you should determine the number of cells that one can be out if start walking on it.

3、题目大意

4、分析与思路

5、题解

6、代码

 1 #include <bits/stdc++.h>
 2  
 3 using namespace std;
 4 typedef long long ll;
 5 typedef unsigned long long ull;
 6 const int N = 1000 + 5;
 7 const int M = 1e9 + 7;
 8 int n,m;
 9 char s[N][N];
10 int ans[N][N];
11 #define multi_case
12 #undef multi_case
13 bool out(int i,int j) {
14     return i <= 0 || i > n || j <= 0 || j > m;
15 }
16 bool dfs(int x,int y) {
17     if(out(x,y)) return true;
18     if(ans[x][y] == 1) return true;
19     if(ans[x][y] == 0) return false;
20     ans[x][y] = false;
21  
22     int dx = x, dy = y;
23     if(s[x][y] == 'W') dx--;
24     else if(s[x][y] == 'S') dx++;
25     else if(s[x][y] == 'A') dy--;
26     else if(s[x][y] == 'D') dy++;
27     ans[x][y] = dfs(dx,dy);
28     return ans[x][y];
29 }
30 void pre() {
31     cin >> n >> m;
32     for(int i = 1; i <= n; i++) {
33         cin >> (s[i]+1);
34     }
35     for(int i = 1; i <= n; i++) {
36         for(int j = 1; j <= m; j++) {
37             ans[i][j] = -1;
38         }
39     }
40 }
41 void solve(int _case) {
42     for(int i = 1; i <= n; i++) {
43         for(int j = 1; j <= m; j++) {
44             if(ans[i][j] == -1) dfs(i,j);
45         }
46     }
47     int cnt = 0;
48     for(int i = 1; i <= n; i++) {
49         for(int j = 1; j <= m; j++) {
50             if(ans[i][j]) cnt++;
51         }
52     }
53     printf("%d\n", cnt);
54 }
55 int main() {
56 //    freopen("data.in","r",stdin);
57 //    freopen("data.out","w",stdout);
58     ios::sync_with_stdio(false);
59     cin.tie(0);
60     int t;
61     pre();
62 #ifdef multi_case
63     cin >> t;
64 #else
65     t = 1;
66 #endif
67     for (int i = 1; i <= t; i++) {
68 //        printf("Case #%d: ",i);
69         solve(i);
70     }
71     return 0;
72 }

(樊总的代码)

 

J. Matrix Subtraction

1、题目链接

https://ac.nowcoder.com/acm/problem/211822

2、题面

Given a matrix M of size n×m and two integers a,b, determine weither it is possible to make all entrys of M zero by repeatedly choosing a×b submatrices and reduce the values in the chosen matrices by 1. If possible, print "^_^" in one line, or print "QAQ" in one line.

3、题目大意

给出一个 n * m 的矩阵,每次对一个 a * b 矩阵的每个元素减 1,求能够将矩阵的元素全部变成 0。

4、分析与思路

5、题解

6、代码

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define fi first
  4 #define se second
  5 #define all(x) (x).begin(),(x).end()
  6 #define mp make_pair
  7 #define pb push_back
  8 #define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0)
  9 #define local freopen("in.text","r",stdin)
 10 #define pi acos(-1)
 11 const int mo=1e9+7;
 12 typedef long long ll;
 13 typedef pair<int,int> pii;
 14 typedef vector<int> vi;
 15 ll qp(ll a,ll b){if(a==0) return 0;ll res=1;a%=mo;for(;b;b>>=1){if(b&1)res=res*a%mo;a=a*a%mo;}return res;}
 16 template<class T> bool read(T & ret)//ll,int,double,float,+/-
 17 {
 18     char c;int sgn;T bit=0.1;if(c=getchar(),c==EOF) return 0;while(c!='-' && c!='.' && (c<'0' || c>'9')) c=getchar();sgn=(c=='-')?-1:1;ret=(c=='-')?0:(c-'0');while(c=getchar(),c>='0' && c<='9') ret=ret*10+(c-'0');if(c==' '||c=='\n') {ret*=sgn;return 1;}while(c=getchar(),c>='0' && c<='9') ret+=(c-'0')*bit,bit/=10;ret*=sgn;return 1;
 19 }
 20  
 21 int a,b,n,m;
 22 ll g[1010][1010];
 23 ll d[1010][1010];
 24 ll sum[1010][1010];
 25  
 26 void add(int x1,int y1,int x2,int y2,ll c)
 27 {
 28     d[x1][y1]+=c;
 29     d[x2+1][y1]-=c;
 30     d[x1][y2+1]-=c;
 31     d[x2+1][y2+1]+=c;
 32 }
 33  
 34 ll get(int x,int y)
 35 {
 36     return sum[x-1][y]+sum[x][y-1]-sum[x-1][y-1]+d[x][y];
 37 }
 38 void solve()
 39 {
 40     memset(sum,0,sizeof sum);
 41     memset(d,0,sizeof d);
 42     scanf("%d%d%d%d",&n,&m,&a,&b);
 43     for(int i=1;i<=n;++i)
 44     {
 45         for(int j=1;j<=m;j++)
 46         scanf("%lld",&g[i][j]);
 47     }
 48     int ok=1;
 49     for(int i=1;i+a-1<=n;++i)
 50     {
 51         for(int j=1;j+b-1<=m;++j)
 52         {
 53             ll now=g[i][j];
 54             ll pre=get(i,j);
 55              
 56              
 57             sum[i][j]=pre;
 58 /*         
 59                 for(int i=1;i<=n;++i)
 60     {
 61         for(int j=1;j<=m;++j)
 62         {
 63             printf("%d ",sum[i][j]);
 64         }
 65         puts("");
 66     }
 67             */
 68             if(pre==now){
 69                 sum[i][j]=pre;
 70                 continue;
 71             }
 72             else if(pre>now) {
 73                 ok=0;break;
 74             }
 75             else {
 76                 ll tt=now-pre;
 77                 add(i,j,i+a-1,j+b-1,tt);
 78                 sum[i][j] = get(i,j);
 79             }
 80              
 81 //          cout<<"fuck:"<<endl;
 82              
 83      
 84         }
 85          
 86         for(int j=m-b+1;j<=m;++j){
 87             sum[i][j]=get(i,j);
 88             if(sum[i][j]!=g[i][j]) {
 89                 ok=0;break;
 90             }
 91         }
 92         if(!ok) break;
 93     }
 94     for(int i=n-a+1;i<=n;++i)
 95     {
 96      
 97         for(int j=1;j<=m;++j)
 98         {
 99             sum[i][j]=get(i,j);
100             if(sum[i][j]!=g[i][j]) {
101                 ok=0;
102                 break;
103             }
104              
105         }
106         if(!ok) break;
107     }
108 /*  for(int i=1;i<=n;++i)
109     {
110         for(int j=1;j<=m;++j)
111         {
112             printf("%d ",sum[i][j]);
113         }
114         puts("");
115     }
116     */
117     if(!ok) puts("QAQ");
118     else puts("^_^");
119 }
120  
121 signed main(){
122      
123     int t;
124     cin>>t;
125     while(t--)
126     {
127         solve();
128     }
129      
130     return 0;
131 }

(lrj 的代码)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章