FYN OI 奋斗之路10~

XJOI奋斗群 群赛15解题报告

原题

https://cn.vjudge.net/contest/187045#overview (Educational Codeforces Round 14)

A - Fashion in Berland

题意

有一串01序列,除非只有一个数,否则若只有一个0,输出“YES”,反之输出“NO”。

题解

简单的计数,特判n=1的情况。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    int a[1010],cnt=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(a[i]==1) cnt++;
    }
    if((cnt==n-1&&n!=1)||(n==1&&cnt==1)) cout<<"YES";
    else cout<<"NO";
}

B - s-palindrome

题意

给出一串字符串,如果字符串左右完全对称,输出”YES“,否则输出”NO”。

题解

从0-字符串长度除以2处依次枚举当前位置的字符,再分类判断,题目本身不难,但判断哪一个字符是对称的有点坑2333.

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s;
    cin>>s;
    int n=s.length();
    for(int i=0;i<=n/2;i++){
        if((s[i]=='A'||s[i]=='H'||s[i]=='I'||s[i]=='M'||s[i]=='O'||s[i]=='T'||s[i]=='U'||s[i]=='V'||s[i]=='W'||s[i]=='X'||s[i]=='Y')&&s[i]==s[n-i-1]) continue;
        else if((s[i]=='w'||s[i]=='v'||s[i]=='o'||s[i]=='x')&&s[i]==s[n-i-1]) continue;
        else if(s[i]=='b'&&s[n-i-1]=='d') continue;
        else if(s[i]=='p'&&s[n-i-1]=='q') continue;
        else if(s[i]=='d'&&s[n-i-1]=='b') continue;
        else if(s[i]=='q'&&s[n-i-1]=='p') continue;
        else {
            cout<<"NIE";
            return 0;
        }
    }
    cout<<"TAK";
}

C - Exponential notation

题意

输入一串字符串代表一个数字(可能有前后导零),输出这个数字用科学计数法表示的结果。

题解

第一眼看到这题还以为是思维题,然后就记录了小数点的位置去分类讨论,做了好久才做出来。应该有比较好的构造解法,这里贴出我的分类AC代码。

#include<bits/stdc++.h>
using namespace std;
int main(){
    bool flag1=false,dian=false;
    string s;
    cin>>s;
    int n=s.length();
    int pos=-1;
    int t1=0,t2=0;
    for(int i=0;i<n;i++){
        if(s[i]=='.'){
            pos=i;
            dian=true;
        }
        if(pos==-1&&s[i]!='0') t1++;
        if(pos!=-1&&i!=pos&&s[i]!='0') t2++;
    }
    if(t1==0&&t2==0) cout<<0;
    else if(!dian){
        int cnt1=0,cnt2=0;
        for(int i=0;i<n;i++){
            if(s[i]=='0') cnt1++;
            else break;
        }
        for(int i=n-1;i>=0;i--){
            if(s[i]=='0') cnt2++;
            else break;
        }
        for(int i=cnt1;i<n-cnt2;i++){
            cout<<s[i];
            if(i==cnt1&&cnt1!=n-cnt2-1) cout<<".";
        }
        if(n-1-cnt1!=0)cout<<"E"<<n-1-cnt1;
    }
    else if(pos==n-1){
        int cnt1=0,cnt2=0;
        for(int i=0;i<n;i++){
            if(s[i]=='0') cnt1++;
            else break;
        }
        for(int i=n-2;i>=0;i--){
            if(s[i]=='0') cnt2++;
            else break;
        }
        for(int i=cnt1;i<=n-cnt2-2;i++){
            cout<<s[i];
            if(i==cnt1&&cnt1!=n-cnt2-2) cout<<".";
        }
        if(n-2-cnt1!=0)cout<<"E"<<n-2-cnt1;
    }
    else if(t2==0){
        int cnt1=0,cnt2=0;
        for(int i=0;i<pos;i++){
            if(s[i]=='0') cnt1++;
            else break;
        }
        for(int i=pos-1;i>=0;i--){
            if(s[i]=='0') cnt2++;
            else break;
        }
        for(int i=cnt1;i<pos-cnt2;i++){
            cout<<s[i];
            if(i==cnt1&&cnt1!=pos-cnt2-1) cout<<".";
        }
        if(pos-1-cnt1!=0)cout<<"E"<<pos-1-cnt1;
    }
    else if(pos==0){
        int cnt1=0,cnt2=0;
        for(int i=1;i<n;i++){
            if(s[i]=='0') cnt1++;
            else break;
        }
        for(int i=n-1;i>=0;i--){
            if(s[i]=='0') cnt2++;
            else break;
        }
        for(int i=1+cnt1;i<n-cnt2;i++){
            cout<<s[i];
            if(i==cnt1+1&&n-cnt2-1!=cnt1+1) cout<<".";
        }
        if(cnt1+1!=0)cout<<"E-"<<cnt1+1;
    }
    else if(t1==0){
        int cnt1=0,cnt2=0;
        for(int i=pos+1;i<n;i++){
            if(s[i]=='0') cnt1++;
            else break;
        }
        for(int i=n-1;i>pos;i--){
            if(s[i]=='0') cnt2++;
            else break;
        }
        for(int i=pos+cnt1+1;i<n-cnt2;i++){
            cout<<s[i];
            if(i==cnt1+pos+1&&n-cnt2-1!=cnt1+pos+1) cout<<".";
        }
        if(cnt1+1!=0)cout<<"E-"<<cnt1+1;
    }
    else{
        int cnt1=0,cnt2=0;
        for(int i=0;i<pos;i++){
            if(s[i]=='0') cnt1++;
            else break;
        }
        for(int i=n-1;i>=pos+1;i--){
            if(s[i]=='0') cnt2++;
            else break;
        }
        for(int i=cnt1;i<pos;i++){
            cout<<s[i];
            if(i==cnt1) cout<<".";
        }
        for(int i=pos+1;i<n-cnt2;i++){
            cout<<s[i];
        }
        if(pos-1-cnt1!=0)cout<<"E"<<pos-1-cnt1; 
    }
}

D - Swaps in Permutation

题意

有n个数字和m种交换方法,每一种方法可以将索引为a的数字与索引为b的数字交换,交换次数没有限制,问最后能交换成的字典序最小的序列。

题解

比较简单的并查集,但因为比较字典序部分耗时比较多,虽然给了5秒,不优化仍然会TLE,因此需要对并查集进行优化,用vector或优先队列都可以,这里贴出我用优先队列优化的AC代码。

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1000010;
int p[MAXN],fa[MAXN],ans[MAXN],num[MAXN];   
int n,m,a,b,root,cnt;
priority_queue <int> que1[MAXN],que2[MAXN];
bool visit[MAXN];
int find(int x){
    if(fa[x]!=x) {
        fa[x]=find(fa[x]);
    }
    return fa[x];
}
void usd(int a,int b){
    int temp1=find(a),temp2=find(b);
    if(temp1!=temp2){
        fa[temp1]=temp2;
    }
}
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++){
        fa[i]=i;
        scanf("%d",&p[i]);  
    }
    for(int i=1;i<=m;i++){
        scanf("%d %d",&a,&b);
        usd(a,b);
//      usd(b,a);
    }
    for(int i=1;i<=n;i++){
        root=find(i);
        if(!visit[root]){
            num[++cnt]=root;
            visit[root]=1;
        }
        que1[root].push(p[i]);
        que2[root].push(-i);
    }
    for(int i=1;i<=cnt;i++){
        while(!que1[num[i]].empty()){
            ans[-que2[num[i]].top()]=que1[num[i]].top();
            que1[num[i]].pop();
            que2[num[i]].pop();
        }
    }
    for(int i=1;i<=n;i++){
        printf("%d ",ans[i]);
    }
}

F - Couple Cover

题意

有n个数与m组询问,从n个数中任取两个数相乘,问能有几种组合使得乘积大于等于询问数,对于每组询问输出一个答案。

题解

拿到题目首先想到可能是前缀之类的预处理,因为询问数很多并且询问本身并不大,因此可以暴力预处理出当前序列中小于等于当前值的数量有多少,之后对于每一组询问输出总数减前一个即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const int MAXN=3000010;
ll a,n,m,q;
ll cnt[MAXN]={0},ans[MAXN]={0};
ll num;
void init(){
    scanf("%I64d",&n);
    for(int i=0;i<n;i++){
        scanf("%I64d",&a);
        cnt[a]++;
    }
    for(int i=1;i*i<MAXN;i++){
        for(int j=i;i*j<MAXN;j++){
            if(i==j) ans[i*j]+=cnt[i]*(cnt[i]-1);
            else ans[i*j]+=2*cnt[i]*cnt[j];
        }
    }
    for(int i=MAXN-2;i>=1;i--){
        ans[i]+=ans[i+1];
    }
    num=(ll)n*(n-1)-ans[1];
}
int main(){
    init();
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%I64d",&q);
        printf("%I64d\n",ans[q]+num);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值