Codeforces Round #479 (Div. 3) 题解

Codeforce官方给的题解 传送门

A. Wrong Subtraction  

交题的传送门:http://codeforces.com/contest/977/problem/A

题意:题意很简单,就是给你一个数,如果能够整除10就直接将该数缩小10倍;否则直接将这个数减一。问k此操作之后,这个数n变为多少?

题解:直接按照题意模拟即可QAQ

代码如下:

 1 //A
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int i,j,m,n,k;
 8     cin>>m>>k;
 9     int flag=0;
10     while(k){
11         while(m%10==0){
12             m/=10;
13             k--;
14             if(k==0) {flag =1;break;}
15         }
16         if(!flag){m--;
17         k--;}
18     }
19     cout<<m<<endl;
20     //cin>>j;
21     return 0;
22 }
View Code

B. Two-gram 

交题的传送门:http://codeforces.com/contest/977/problem/B

题意:这个题意就是:给你一个字符串,然后这个字符串中任意连续的两个字符组合成的字符串,在原字符串中出现最多次数的字符串给找出来。

题解:直接按照题意模拟,将所截的字符串用map存起来并计数,然后找到最大次数并且将字符串记录,打出来就好了QAQ

代码如下:

 1 //B
 2 #include <iostream>
 3 #include <map>
 4 using namespace std;
 5 map<string, int> mp;
 6 int main()
 7 {
 8     int i, j, m, n, k;
 9     string s, p, q;
10     cin >> m;
11     cin >> s;
12     int maxn = -1;
13     for (i = 0; i < m-1; i++)
14     {
15         q=s.substr(i,2);
16         //cout<<i<<q<<endl;
17         mp[q]++;
18         if (mp[q] > maxn)
19         {
20             maxn = mp[q];
21             p = q;
22         }
23     }
24     cout<<p<<endl;
25     //cin>>k;
26     return 0;
27 }
View Code

C. Less or Equal  

交题的传送门:http://codeforces.com/contest/977/problem/C

题意:给一个整数序列,是否找到一个数x,找到k个数字<=x,找到输出x,不能输出-1。看第二组数据,要找到两个数字,排序后出现1,3,3,会出现三个数字小于等于3,所以不能找到。

           一个坑点,k=0的时候需要分类讨论,如果发现最小的数字是1的话,不能输出0,因为要求输出1~1e9之间的数,否则输出a[0]-1就可以QAQ

题解:排序以后分类判断即可。注意k=0时分类讨论

代码如下:

 1 //C
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<string.h>
 5 #include<stdlib.h>
 6 #include<bits/stdc++.h>
 7 using namespace std;
 8 int a[200005];
 9 bool cmp(int x,int y)
10 {
11     return x<y;
12 }
13 int main()
14 {
15     int i,j,m,k,n;
16     cin>>n>>k;
17     for(i=0;i<n;i++){
18         cin>>a[i];
19     }
20 
21     sort(a,a+n,cmp);
22     if(n==k){
23         cout<<a[k-1]<<endl;
24         return 0;
25     }
26     if(k==0){
27         if(a[0]==1){
28             puts("-1");
29         }
30         else{
31             puts("1");
32         }
33 
34         return 0;
35     }
36     if(a[k]==a[k-1]){
37         puts("-1");
38         //cin>>i;
39         return 0;
40     }
41     cout<<a[k-1]<<endl;
42     //cin>>i;
43     return 0;
44 }
View Code

D. Divide by three, multiply by two 

交题的传送门:http://codeforces.com/contest/977/problem/D

题意:将给出的序列按照题目要求输出。选取一个数,然后通过除以3或者乘以2得到下一个数,然后将这些数按这个顺序直接打出来即可QAQ,数据保证有解

题解:将所有可以除以3的数全部记录次数存到数组里,按照从大到小的顺序直接排,将这个原来的数与这个新数组对应,从而输出来所有的数组。

其实一开始我用DFS去写,发现写不出来,结束了看大神代码,恍然大悟了。还是自己太菜了QAQ

代码如下:

 1 //D
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 typedef long long LL;
 5 int count3(LL x)
 6 {
 7     int ret=0;
 8     while(x % 3 == 0)
 9     {
10         ret++;
11         x /= 3;
12     }
13     return ret;
14 }
15 int n;
16 vector<pair<int,LL>> v;
17 int main()
18 {
19     cin>>n;
20     v.resize(n);
21     for(int i=0; i<n; i++)
22     {
23         cin>>v[i].second;
24         v[i].first=-count3(v[i].second);
25         //cout<<v[i].first<<endl;
26     }
27     sort(v.begin(), v.end());
28     for(int i=0; i<n; i++)
29         printf("%lld%c", v[i].second, " 
"[i + 1 == n]);
30 }
View Code

还有两个dalao的骚操作,大家可以看下

 1 //D
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 const int N=100+10;
 5 typedef long long int ll;
 6 ll a[N],b[N];
 7 map<ll,ll>m;
 8 int main()
 9 {
10     int n;
11     scanf("%d",&n);
12     m.clear();
13     for(int i=1; i<=n; i++)
14     {
15         scanf("%lld",a+i);
16         m[a[i]]=1;
17     }
18     sort(a+1,a+1+n);
19     int l=100,r=100;
20     b[l]=a[1];
21     while(r-l<n-1)
22     {
23         //cout<<l<<' '<<r<<endl;
24         if(m[b[r]*2]==1)
25         {
26             m[b[r]*2]=0;
27             r++;
28             b[r]=b[r-1]*2;
29         }
30         else if(b[r]%3==0&&m[b[r]/3]==1)
31         {
32             m[b[r]/3]=0;
33             r++;
34             b[r]=b[r-1]/3;
35         }
36         else if(m[b[l]*3]==1)
37         {
38             m[b[l]*3]=0;
39             l--;
40             b[l]=b[l+1]*3;
41         }
42         else if(b[l]%2==0&&m[b[l]/2]==1)
43         {
44             m[b[l]/2]=0;
45             l--;
46             b[l]=b[l+1]/2;
47         }
48     }
49     for(int i=l; i<=r; i++)
50     {
51         printf("%lld ",b[i]);
52     }
53     return 0;
54 }
View Code
 1 //D
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 typedef long long ll;
 5 int highest_power(ll n,int k)   //k is 3 or 2
 6 {
 7     int count=0;
 8     while(n%k==0)
 9     {
10         count++;
11         n=n/k;
12     }
13     return(count);
14 }
15 bool ispresent(ll num,ll n,ll a[])
16 {
17     for(int i=0; i<n; i++)
18     {
19         if(a[i]==num)
20             return(1);
21     }
22     return(0);
23 }
24 int main()
25 {
26     ll n;
27     cin>>n;
28     ll a[n];
29     for(ll i=0; i<n; i++)cin>>a[i];
30     pair <int,int> start;
31     int index=-1;
32     start= {-999999,999999};
33     for(int i=0; i<n; i++)
34     {
35         int temp3=highest_power(a[i],3);
36         int temp2=highest_power(a[i],2);
37         //cout<<temp3<<" "<<temp2<<endl;
38         if((temp3>=start.first)&&(temp2<=start.second))
39         {
40             start= {temp3,temp2};
41             index=i;
42         }
43         //cout<<"start: "<<start.first<<" "<<start.second<<endl;
44     }
45     cout<<a[index]<<" ";
46     ll curr=a[index];
47     for(int i=2; i<=n; i++)
48     {
49         if(curr%3==0)
50         {
51             if(ispresent(curr/3,n,a))
52             {
53                 curr=curr/3;
54                 cout<<curr<<" ";
55             }
56             else
57             {
58                 curr=2*curr;
59                 cout<<curr<<" ";
60             }
61         }
62         else
63         {
64             curr=2*curr;
65             cout<<curr<<" ";
66         }
67     }
68 }
View Code

E. Cyclic Components 

交题的传送门:http://codeforces.com/contest/977/problem/E

题意:给你一些点与点直接的连通情况,这个是无向图,算出这个图中有几个圈。注意:圈中所有的节点的度为2

题解:用并查集直接统计,若两个节点的父亲节点是同一个,那么增加一个圈。算出圈的个数QAQ

代码如下:

 1 //E
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 
 5 struct node
 6 {
 7     int u;
 8     int v;
 9 }e[200005];
10 int du[200005],coun;
11 int father[200005];
12 
13 void init(int x)
14 {
15     memset(du,0,sizeof(du));
16     for(int i=1;i<=x;i++)
17     {
18         father[i]=i;
19     }
20 }
21 int Find(int x)
22 {
23     if(x==father[x]) return x;
24     return father[x]=Find(father[x]);
25 }
26 
27 void Union(int x,int y)
28 {
29     int dx=Find(x);
30     int dy=Find(y);
31     if(dx==dy) coun++;
32     else father[dx]=dy;
33 }
34 
35 int main()
36 {
37     int i,j,m,n,k,x,y;
38     cin>>m>>n;
39     init(m);
40     for(i=1;i<=n;i++)
41     {
42         cin>>e[i].u>>e[i].v;
43         du[e[i].u]++;
44         du[e[i].v]++;
45     }
46     coun=0;
47     for(i=1;i<=n;i++)
48     {
49         if(du[e[i].u]==2&&du[e[i].v]==2){
50             Union(e[i].u,e[i].v);
51         }
52     }
53     cout<<coun<<endl;
54     return 0;
55 }
View Code

还有位dalao写的,参考一下

 1 //E
 2 #include<iostream>
 3 #include<string.h>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<map>
 7 #include<string>
 8 #include<stdio.h>
 9 #include<vector>
10 #include<stack>
11 #include<set>
12 using namespace std;
13 #define INIT ios::sync_with_stdio(false)
14 #define LL long long int
15 
16 struct node {
17     int id;
18     int count;
19 };
20 int dp[2 * 100005];
21 vector<int>mm[200005];
22 void init() {
23     for (int i = 0;i < 2 * 100005;i++) {
24         dp[i] = i;
25     }
26 }
27 
28 int _find(int x) {
29     if (dp[x] != x) {
30         return dp[x] = _find(dp[x]);
31     }
32     return dp[x];
33 }
34 
35 void _union(int  x, int y) {
36     int xx = _find(x);
37     int yy = _find(y);
38     if (xx < yy) {
39         dp[xx]= yy;
40     }
41     else {
42         dp[yy] = xx;
43     }
44 }
45 
46 int main() {
47     int n, m;
48     map<int, int>mp;//存每个节点的度
49     while (cin >> n >> m)
50     {
51         mp.clear();
52         init();
53         int a, b;
54         int ans = 0;
55         for (int i = 0;i < m;i++) {
56             cin >> a >> b;
57             mp[a]++;
58             mp[b]++;
59             if (_find(a) != _find(b)) {
60                 _union(a, b);
61             }
62         }
63         //通过父节点把连通图存进一个vector数组
64         for (int i = 1;i <= n;i++) {
65             mm[_find(i)].push_back(i);
66         }
67         for (int i = 1;i <= n;i++) {
68             //连通图至少要有3个点
69             if (mm[i].size() > 2) {
70                 int flag = 1;
71                 for (int j = 0;j < mm[i].size()&&flag;j++) {
72                     //只要有一个度不为2就跳出
73                     if (mp[mm[i][j]] != 2) {
74                         flag = 0;
75                     }
76                 }
77                 if (flag)ans++;
78             }
79         }
80         cout << ans << endl;
81     }
82     return 0;
83 }
View Code

F. Consecutive Subsequence

交题的传送门:http://codeforces.com/contest/977/problem/F

题意:给出一个n和n个数的序列,然后让你找到满足两个数之间相差为1的存在的最长的序列,让你输出他们的下标。

题解:

跟最长递增子序列差不多,但是他的数据有给的还是挺大的,两种方法,离散化一下,或者map搞一下,map比较好写,所以直接map存一下。接着你只需要保存最长的序列最后一个数的位置和数就可以,那么怎么保存呢?

因为我们需要顺序的从这个序列里找,可以每次把进来的数标记由前面一个数 + 1得到,即可以得到到这个数为止的最长序列的长度。

比如 3 3 4 7 5 6 8 

3 的时候 我们就以m【2】 + 1 得到这个m【3】,但是因为m【2】没出现过,所以直接就是1,然后下一个3也是如此,4的时候就由m【3】 + 1 ,所以m【4】 = 2,然后依次到8,就可以在m【8】的位置保存到从0到8中,最长的序列长度。

边赋值,边找到最大值的下标和数,然后找到以后,有个最大值,用最大值减去长度 + 1是不是就可以得到他的起始数字了,然后再遍历一遍序列,找每个数就可以了,输出下标。

由于这道题目不知道如何表达,参考了这位大佬的题解QAQ,(实际上就是自己太菜了555555555

参考了这位dalao的题解:https://blog.csdn.net/qq_38185591/article/details/80256487

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[200005];
 4 int main()
 5 {
 6     int i,j,m,n,k,x;
 7     cin>>m;
 8     map<int,int> dp;
 9     vector<int> ve;
10     for(i=0;i<m;i++)
11     {
12         cin>>a[i];
13     }
14     int ans=0;
15     int last=0;
16     for(i=0;i<m;i++)
17     {
18         x=a[i];
19         dp[x]=dp[x-1]+1;
20         if(ans<dp[x]){
21             ans=dp[x];
22             last=x;
23         }
24     }
25     cout<<ans<<endl;
26     for(i=m-1;i>=0;i--){
27         if(a[i]==last){
28             ve.push_back(i+1);
29             last--;
30         }
31     }
32     reverse(ve.begin(),ve.end());
33     for(i=0;i<ve.size();i++){
34         if(i==ve.size()-1){cout<<ve[i]<<endl;break;}
35         cout<<ve[i]<<' ';
36     }
37     return 0;
38 }
View Code
原文地址:https://www.cnblogs.com/Fantastic-Code/p/9037055.html