一次边吃饭边写的题的神奇故事...
A. Wrong Subtraction
传送门:http://codeforces.com/contest/977/problem/A
#include <cmath> #include <iostream> #include <cstdio> #include <string> #include <cstring> using namespace std; /*Tanya通过以下算法: 如果该号码的最后一位数字不为零,则将该号码减1; 如果该数字的最后一位数字为零,她将该数字除以10。 给你一个整数n。进行k次减法的答案。 */ int main(){ int n,k; cin>>n>>k; for(int i=1;i<=k;i++){ if(n%10==0) n/=10; else n-=1; } printf("%d\n",n); return 0; }
B. Two-gram
传送门:http://codeforces.com/contest/977/problem/B
#include <cmath> #include <iostream> #include <cstdio> #include <string> #include <cstring> using namespace std; /* ss是一个有序对(即长度为二的字符串)的大写拉丁字母。 例如,“AZ”,“AA”,“ZA” 。给你一个字符串s,由n个大写拉丁字母组成。 查找给定字符串中包含的任何ss字符作为子字符串(即字符串的两个连续字符)的最大次数。 例如,对于字符串s =“BBAABBBA”,答案是ss串“BB”,其包含在s中三次 请注意,ss的出现可以相互重叠。 */ const int MAXN = 1e5 + 10; inline int read() { //读入优化 char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar(); return x * f; } char s[MAXN]; string ss[MAXN];//字符串集合 int main(){ int N=read(); scanf("%s",s+1);//从1开始 for(int i = 1; i <= N - 1; i++) ss[i] += s[i], ss[i] += s[i + 1];//连续两个组成ss int mx = 0; string anss; for(int i = 1; i <= N - 1; i++) { int now = 0; for(int j = 1; j <= N - 1; j++) if(ss[i] == ss[j]) now++; if(now>mx) mx=now,anss=ss[i];//更新答案为now } cout<<anss<<endl; return 0; }
C. Less or Equal
传送门:http://codeforces.com/contest/977/problem/C
#include <cmath> #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <algorithm> using namespace std; /* 给一个整数序列,是否找到一个数x,(正好只有)k个数字<=x,找到输出x, 不能则输出-1。看第二组数据,要找到两个数字,排序后出现1,3,3, 会出现三个(>2)数字小于等于3,所以不能找到。注意,k=0的时候需要分类讨论, k=0,a[1]!=1,输出-1;k=0其他情况,输出1即可。 分析》排序,判断k位置和k+1位置的数是否相等。特判k=0,a[1]=1的情况。 */ const int MAXN=1e6+10; inline int read() { //读入优化 char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar(); return x * f; } int n,k,a[MAXN]; int main(){ n=read(); k=read(); for(int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+n+1); if((a[k]==a[k+1])||(k>n)||(k==0&&a[1]==1)) puts("-1"); else if(k==0) printf("1"); else printf("%d",a[k]);//直接输出a[k]即可 return 0; }
D. Divide by three, multiply by two
传送门:http://codeforces.com/contest/977/problem/D
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<string> #include<iostream> #include<map> #include<vector> #include<set> #include<queue> using namespace std; typedef long long ll; /* D:4 8 6 3 12 9 把这个序列排成一个这样的序列, 前一位是后一位数的一半或者3倍,即9 3 6 12 4 8 题解:直接按对3有更多约数的多少来排(前一位是后一位的3倍), 有相同个则从小到大(也就是前一位是后一位数的一半) */ int num3(ll x){ ll len = 0; while (x % 3 == 0 && x){ x /= 3; len++; } return len; } bool cmp(ll a, ll b){ if(num3(a)!=num3(b)) return num3(a)>num3(b); else return a<b; } ll a[110]; int main(){ int n; scanf("%d", &n); for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n,cmp);//按照题目要求的顺序排序 for(int i=0;i<n;i++){ cout<<a[i]; printf("%c",i==n-1?'\n':' '); } return 0; }
E. Cyclic Components
传送门:http://codeforces.com/contest/977/problem/E
#include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <string> #include <iostream> #include <map> #include <vector> #include <set> #include <queue> using namespace std; typedef long long ll; /* E. Cyclic Components 题意简化: 给定点的个数和各条边,问有多少个环 分析:环-> 一个点对应两次,使用并查集 */ const int maxn=2e5+10; int pre[maxn],edg[maxn],cnt; struct node{ int x,y; }a[maxn]; 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){ for(int i=0;i<maxn;i++) pre[i]=i; memset(edg,0,sizeof(edg)); for(int i=0;i<n;i++){ cin>>a[i].x>>a[i].y; edg[a[i].x]++; edg[a[i].y]++; } cnt=0; for(int i=0;i<m;i++){ if(edg[a[i].x]==2&&edg[a[i].y]==2) join(a[i].x,a[i].y); } cout<<cnt<<endl; } return 0; }
F. Consecutive Subsequence
传送门:http://codeforces.com/contest/977/problem/F
#include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <string> #include <iostream> #include <map> #include <vector> #include <set> #include <queue> using namespace std; typedef long long ll; /* F》在数组中找出最长的递增子序列的长度以及下标位置。 样例》3 3 4 7 5 6 8 最长的子序列为3 4 5 6,下标为1 3 5 6或2 3 5 6。 题解》用map进行dp,mp[i]表示以i数字开头的最长的递增子序列的长度, 转移方程mp[i]=max(mp[i],mp[i-1]+1) 最后找出map里面子序列长度最长的数字i,倒着输出就行了。 */ 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; } //此题代码来自某位dalao qwq
——时间划过风的轨迹,那个少年,还在等你。