Codeforces Round #479 (Div. 3)解题报告
题目链接: http://codeforces.com/contest/977
A. Wrong Subtraction
题意
给定一个数x,求n次操作输出。操作规则:10的倍数则除10,否则减1
直接写,手速题,没啥好说的
B. Two-gram
题意
求出现次数最多的连续两个字符
还是签到题,我居然很麻烦地用了map,= =算了,思路畅通都无所谓了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include<stdio.h> #include<algorithm> #include<string.h> #include<string> #include<map> using namespace std; int main() { char a[100],s[5],ss[5]; int n; while(cin>>n) { cin>>a; map<string,int>mp; int MAX=-1; for(int i=0;i<strlen(a)-1;i++) { s[0]=a[i]; s[1]=a[i+1]; mp[s]++; //cout<<s<<endl; if(mp[s]>MAX) MAX=mp[s],ss[0]=a[i],ss[1]=a[i+1]; } cout<<ss[0]<<ss[1]<<endl; } return 0; }
C. Less or Equal
题意
给一串数组,是否找到一个数x,找到k个数字<=x,找到输出x,不能输出-1。
第二组,要找到两个数字,排序后出现1,3,3,会出现三个数字小于等于3,所以不能找到。
注意下k==0的时候就好了,没啥好说的
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <map> #define ll long long using namespace std; const int maxn=2e5+10; int a[maxn]; int main() { int m,k; while(cin>>m>>k) { for(int i=0;i<m;i++) cin>>a[i]; sort(a,a+m); if(k==0) { if(a[0]==1) puts("-1"); else cout<<a[0]-1<<endl; } else if(k==m) cout<<a[k-1]<<endl; else { if(a[k-1]==a[k]) puts("-1"); else cout<<a[k-1]<<endl; } } return 0; }
D. Divide by three, multiply by two
题意
直接看样例吧 4 8 6 3 12 9 把这个序列排成一个这样的序列, 前一位是后一位数的一半或者3倍,所以排序后是这样 9 3 6 12 4 8
dfs或者直接双重for循环都可以,不过赛后看到个数学思路的题解,觉得很有灵性= =
直接按对3有更多约数的多少来排(前一位是后一位的3倍),有相同个则从小到大(也就是前一位是后一位数的一半)
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <map> #define ll long long using namespace std; const int maxm=2e5+10; const int maxn=1e5+10; ll a[105]; ll s(ll num) { ll cnt=0; while(num%3==0) { cnt++; num/=3; } return cnt; } bool cmp(ll x,ll y) { if(s(x)!=s(y)) return s(x)>s(y); else return x<y; } int main() { int n; while(cin>>n) { for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n,cmp); for(int i=0;i<n;i++) printf("%lld%c",a[i],i==n-1?'\n':' '); } }
E. Cyclic Components
题意
给定点的个数和各条边,问有多少个环
既然是环,一个点就会对应两次啊,直接并查集啊,巴拉巴拉,水水水就过去了
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <map> #define ll long long using namespace std; const int maxn=2e5+10; int pre[maxn],edg[maxn],cnt; struct node { int u,v; }a[maxn]; void iint() { for(int i=0;i<maxn;i++) pre[i]=i; } int ffind(int x) { if(x==pre[x]) return x; return pre[x]=ffind(pre[x]); } void join(int x,int y) { x=ffind(x),y=ffind(y); if(x!=y) pre[x]=y; else cnt++; } int main() { int m,n; while(cin>>m>>n) { iint(); memset(edg,0,sizeof(edg)); for(int i=0;i<n;i++) { cin>>a[i].u>>a[i].v; edg[a[i].u]++; edg[a[i].v]++; } cnt=0; for(int i=0;i<m;i++) { if(edg[a[i].u]==2&&edg[a[i].v]==2) join(a[i].u,a[i].v); } cout<<cnt<<endl; } return 0; }
F. Consecutive Subsequence
题意
给你一个数组找出最长的递增子序列的长度以及下标位置。
例如: 第一组样例 3 3 4 7 5 6 8
最长的子序列为3 4 5 6,长度为4。
下标为1 3 5 6或2 3 5 6
觉得dp才是正解,贴个别人的http://www.bubuko.com/infodetail-2595514.html
可是比赛时候不知道为什么被我map玄学给过了2333
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <map> #define ll long long using namespace std; const int maxn=2e5+10; int a[maxn]; int main() { ios::sync_with_stdio(false); int n,tmp; while(cin>>n) { map<int,int>mp; int max_pos=-1,Max=-1; for(int i=1;i<=n;i++) { cin>>a[i]; mp[a[i]]=mp[a[i]-1]+1; if(mp[a[i]]>Max) Max=mp[a[i]],tmp=a[i],max_pos=i; } int u=tmp-Max+1; cout<<Max<<endl; bool f=true; for(int i=1;i<=max_pos;i++) { if(a[i]==u) { if(f) cout<<i,f=false; else cout<<" "<<i; u++; } } cout<<endl; } return 0; }