Codeforce官方给的题解 传送门
A. Wrong Subtraction
交题的传送门:http://codeforces.com/contest/977/problem/A
题意:题意很简单,就是给你一个数,如果能够整除10就直接将该数缩小10倍;否则直接将这个数减一。问k此操作之后,这个数n变为多少?
题解:直接按照题意模拟即可QAQ
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
B. Two-gram
交题的传送门:http://codeforces.com/contest/977/problem/B
题意:这个题意就是:给你一个字符串,然后这个字符串中任意连续的两个字符组合成的字符串,在原字符串中出现最多次数的字符串给找出来。
题解:直接按照题意模拟,将所截的字符串用map存起来并计数,然后找到最大次数并且将字符串记录,打出来就好了QAQ
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
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时分类讨论
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
D. Divide by three, multiply by two
交题的传送门:http://codeforces.com/contest/977/problem/D
题意:将给出的序列按照题目要求输出。选取一个数,然后通过除以3或者乘以2得到下一个数,然后将这些数按这个顺序直接打出来即可QAQ,数据保证有解
题解:将所有可以除以3的数全部记录次数存到数组里,按照从大到小的顺序直接排,将这个原来的数与这个新数组对应,从而输出来所有的数组。
其实一开始我用DFS去写,发现写不出来,结束了看大神代码,恍然大悟了。还是自己太菜了QAQ
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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, " \n"[i + 1 == n]); 30 }
还有两个dalao的骚操作,大家可以看下
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
E. Cyclic Components
交题的传送门:http://codeforces.com/contest/977/problem/E
题意:给你一些点与点直接的连通情况,这个是无向图,算出这个图中有几个圈。注意:圈中所有的节点的度为2
题解:用并查集直接统计,若两个节点的父亲节点是同一个,那么增加一个圈。算出圈的个数QAQ
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
还有位dalao写的,参考一下
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
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
代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }