一次边吃饭边写的题的神奇故事...
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
——时间划过风的轨迹,那个少年,还在等你。