[比賽][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 的代碼)

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