链接:http://codeforces.com/contest/988
来源:Codeforces
文章目录
A - Diverse Team
找到一个数组中不同的数字是否大于等于>k个,如果满足输出YES,并且输出他们的位置,否则输出NO,遍历去重即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int Max_n=110;
int a[Max_n];
struct B{
int val,pos;
}b[Max_n];
int main(){
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int cnt=1;
b[cnt].val=a[1];
b[cnt++].pos=1;
bool flag=false;
for(int i=2;i<=n;i++){
bool flag1=false;
for(int j=1;j<cnt;j++){
if(a[i]==b[j].val){
flag1=true;
break;
}
}
if(!flag1){
b[cnt].val=a[i];
b[cnt++].pos=i;
}
}
if(cnt-1>=k) flag=true;
if(flag){
printf("YES\n");
for(int i=1;i<=k;i++)
printf("%d%c",b[i].pos,i==k?'\n':' ');
}else{
printf("NO\n");
}
return 0;
}
B - Substrings Sort (string)
判断短的字符串是否是长的字符串的字串,用string的find函数即可解决。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int Max_n=110;
string a[Max_n];
bool cmp(string &a,string &b){
return a.length()<b.length();
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1,cmp);//按照字符串的长短进行排序
//for(int i=1;i<=n;i++)
// cout<<a[i]<<endl;
bool flag=true;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(i==j) continue;
string::size_type pos=a[j].find(a[i]);
//从第一个字符串开始,寻找其在后面的字符串中是否出现。
//返回a[j].npos说明a[i],在a[j]这个字符串中没有出现。
if(pos==a[j].npos) flag=false;
}
}
if(flag){
cout<<"YES"<<endl;
for(int i=1;i<=n;i++)
cout<<a[i]<<endl;
}else{
cout<<"NO"<<endl;
}
return 0;
}
C - Equal Sums
给你k个序列,让你判断其中是否存在两个序列可以满足这样的条件:在这两个序列中分别去除一个元素后,这个两个序列的和相等。
#include<bits/stdc++.h>
using namespace std;
const int Max_n=200005;
typedef long long LL;
typedef pair<int,int>P;//相当于结构体
map<int,P>m;
int a[Max_n];
int main(){
int k;
scanf("%d",&k);
bool flag=false;
for(int i=1;i<=k;i++){
int n,sum=0;
scanf("%d",&n);
for(int j=1;j<=n;j++){
scanf("%d",&a[j]);
sum+=a[j];//求出每个序列的和
}
for(int j=1;j<=n;j++){
if(flag) break;//标记是否找到了满足条件的两个序列,如果已经找到就跳出判断
if(m.count(sum-a[j])&&m[sum-a[j]].first!=i){
//二分的查找sum-a[j]之前已经出现过的次数,并且之前的和不是由当前这个序列产生的
printf("YES\n");
printf("%d %d\n",m[sum-a[j]].first,m[sum-a[j]].second);//输出之前的序列值
printf("%d %d\n",i,j);//当前的序列值。
flag=true;
}
m[sum-a[j]]=P(i,j);//将每一个和的位置都记录下来
}
}
if(!flag) printf("NO\n");
return 0;
}
D - Points and Powers of Two
题目给你一个序列,让你找到其中存在最长的自己满足这样的条件:每两个数的差都是2k,满足条件的子集的个数最多有三个数,并且他们是一个等差数列,也就是说这三个数满足x x+2k x+2k+2k
证明:https://www.cnblogs.com/WTSRUVF/p/9531118.html
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Max_n=2e5+10;
ll a[Max_n];
set<ll>s;
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
s.insert(a[i]);//去重
}
bool flag=false;
for(int i=1;i<=n;i++){
for(ll j=1;j<=2e9+10;j*=2){//二分的去查找满足条件的数
if(s.count(a[i]+j)&&s.count(a[i]+j+j)){
printf("3\n");
printf("%lld %lld %lld\n",a[i],a[i]+j,a[i]+2*j);
flag=true;
break;
}
}
if(flag) break;
}
if(!flag){//没有找到3个数,判断是否有两个数满足
for(int i=1;i<=n;i++){
for(ll j=1;j<=2e9+10;j*=2){
if(s.count(a[i]+j)){
printf("2\n");
printf("%lld %lld\n",a[i],a[i]+j);
flag=true;
break;
}
}
if(flag) break;
}
}
if(!flag) printf("1\n%lld\n",a[1]);
return 0;
}
E - Divisibility by 25
给你一个数,你能够交换其中相邻的数,问你最少交换多少次后这个数能够被25整除。我们知道一个数能够被25整除,那么他的后两位数一定是00,25,50,75,那么我们可以将这四种情况的交换次数全部求出来,然后找到最小的交换次数即可。还要注意如果交换完成后,判断是否有前导零的出现。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char a[20],b[20];
int get_times(char x,char y,int n,int ans){
for(int i=0;i<n;i++) b[i]=a[i];
bool flag_a=false,flag_b=false;
int cnt=0;
for(int i=n-1;i>=0;i--){//有多个满足条件的数,从最后一个开始找
if(b[i]==y){
flag_b=true;
for(int j=i;j<n-1;j++){
swap(b[j],b[j+1]);
cnt++;
}
break;
}
}
for(int i=n-2;i>=0;i--){
if(b[i]==x){
flag_a=true;
for(int j=i;j<n-2;j++){
swap(b[j],b[j+1]);
cnt++;
}
break;
}
}
if(flag_a&&flag_b){//两个都找到了,说明次数被更新了
if(b[0]!='0')
ans=min(ans,cnt);
else{
for(int i=0;i<n-2;i++){
if(b[i]!='0'){
cnt+=i;
ans=min(ans,cnt);
break;
}
}
}
}
return ans;
}
int main(){
scanf("%s",a);
int n=strlen(a);
int ans=100;
ans=get_times('0','0',n,ans);
ans=get_times('2','5',n,ans);
ans=get_times('5','0',n,ans);
ans=get_times('7','5',n,ans);
if(ans==100) printf("-1\n");
else printf("%d\n",ans);
return 0;
}