AtCoder Beginner Contest 347(A~D)

文章涉及C++编程中的三个问题:处理整除并输出结果,计算字符串子串数量,以及安排假期和工作日计划以确保全部在假期中,同时解决异或问题。作者使用了循环、条件判断和模拟方法来解决这些问题。
摘要由CSDN通过智能技术生成

A - Divisible

如果序列里面的数能被k整除,就整除后输出

#include <bits/stdc++.h>
//#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define debug(a) cout<<#a<<"="<<a<<endl
#define all(x) x.begin(),x.end()
#define EX exit(0)
#define fr first
#define se second
#define endl '\n'
using namespace std;
using ll=long long;

void solve(){
    int n,k;
    cin>>n>>k;

    int a[n+1];
    per(i,1,n)cin>>a[i];

    per(i,1,n){
        if(a[i]%k==0){
            cout<<a[i]/k<<" ";
        }
    }
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

B - Substring

串S,有几个不同的子串,暴力枚举。

#include <bits/stdc++.h>
//#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define debug(a) cout<<#a<<"="<<a<<endl
#define all(x) x.begin(),x.end()
#define EX exit(0)
#define fr first
#define se second
#define endl '\n'
using namespace std;
using ll=long long;

void solve(){
    string s;
    cin>>s;

    map<string,bool>f;

    per(len,1,s.length()){
        per(i,0,s.length()-1){
            if(i+len<=s.length())
            f[s.substr(i,len)]=true;
        }
    }

    cout<<f.size();
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

C - Ideal Holidays

A假期,B工作日,A假期,B工作日,这么轮回。

问N个plan是否能全部都在假期里面。

因为plan是afterday,所以plan序列是固定的,我们只需要左右移动这个序列,看是否能恰好嵌入到假期里面。

所以把plan1令为a的第一天,那么我们现在可以向右移动a-1天,接下来分类讨论即可。

#include <bits/stdc++.h>
#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define debug(a) cout<<#a<<"="<<a<<endl
#define all(x) x.begin(),x.end()
#define EX exit(0)
#define fr first
#define se second
#define endl '\n'
using namespace std;
using ll=long long;

void solve(){
    int n,a,b;
    cin>>n>>a>>b;

    int d[n+1];
    per(i,1,n)cin>>d[i];

    rep(i,n,2)d[i]-=d[i-1];

    int r=a-1;

    int now=1;
    per(i,2,n){
        now+=d[i];
        if(now>a+b){
            if(now%(a+b)==0)now=a+b;
            else now%=a+b;
        }

        if(now>=a+1 and now<=a+b){//如果在这里面,我们需要往右移动到a=1
            if(r>=a+b-now+1){
                r-=a+b-now+1;//r由最小的决定,所以这里只需要减掉
                now=1;
            }else{
                cout<<"No";
                return;
            }
        }else{
            r=min(r,a-now);//如果落在同一个里面,取最小值
        }
    }
    cout<<"Yes";
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

补题:D - Popcount and XOR 

输出任意一组X,Y

满足以上条件。

假设C=13,即二进制

1110,因为要求异或后相等,所以C上是1的地方,一定是1 xor 0,即X那个位是1 y那个位是0,反之亦可。

如果C上是0,考虑X和Y那一位都是1,或者都是0。

所以我们先把C上是1的地方放好1,0,并且交替使用a和b,让a和b最终使用之后能相等,这样最后异或才会不影响答案,如果a!=b,最终答案一定不会等于C。

如果a,b还有剩,我们就往高位放1,不影响答案(注意放的位数超过61了就超出题目范围了,需要判断特殊情况)

那么答案就呼之欲出了(正常数学做可能没这么麻烦,本蒟蒻只会模拟)

需要注意的是不要在运算式中使用pow函数,请调用计算结果(这里建议直接使用位运算)。

如 int a=pow(2,60),int ans=a,cout<<a

如果直接使用 cout<<pow(2,60),会造成错误。

#include <bits/stdc++.h>
#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define debug(a) cout<<#a<<"="<<a<<endl
#define all(x) x.begin(),x.end()
#define EX exit(0)
#define fr first
#define se second
#define endl '\n'
using namespace std;
using ll=long long;

int popcount(int x){
    int cnt=0;
    while(x)cnt+=x&1,x>>=1;
    return cnt;
}

void solve(){
    int a,b,c;
    cin>>a>>b>>c;


    //x xor y =C

    //位不一样输出1,一样输出0

    //x,只有a个1
    //y,只有b个1

    //
    //
    //0111

    stack<int>s;
    if(c==0)s.push(0);
    while(c){
        s.push(c%2);
        c>>=1;
    }

    deque<int>x,y;

    while(s.size()){
        int now=s.top();
        s.pop();

        if(now==1){
            if(b>=a){
                if(b==0){
                    cout<<-1;
                    return;
                }
                b--;
                x.push_back(0);
                y.push_back(1);
            }else{
                if(a==0){
                    cout<<-1;
                    return;
                }
                a--;
                x.push_back(1);
                y.push_back(0);
            }
        }else{//now=0
            //放两个1或者两个0

            x.push_back(-1);
            y.push_back(-1);//暂定
        }
    }

//    for(auto i:x){
//        cout<<i;
//    }cout<<endl;
//    for(auto i:y){
//        cout<<i;
//    }cout<<endl;

    deque<int>newx,newy;

    int ansx=0,ansy=0,cnt=0;
    if(a+b){//a+b还有剩余 1
        if(a!=b){//不相同无解
            cout<<-1;
            return;
        }

        int cul=a;//有cul个位需要放1

        per(i,0,x.size()-1){
            if(x[i]==-1){
                if(cul){
                    cul--;
                    newx.push_back(1);
                    newy.push_back(1);
                }else{
                    newx.push_back(0);
                    newy.push_back(0);
                }
            }else{
                newx.push_back(x[i]);
                newy.push_back(y[i]);
            }
        }

        while(cul){
            cul--;
            newx.push_front(1);
            newy.push_front(1);
        }
    }else{
        //暂定全部用0
        per(i,0,x.size()-1){
            if(x[i]==-1){
                newx.push_back(0);
                newy.push_back(0);
            }else{
                newx.push_back(x[i]);
                newy.push_back(y[i]);
            }
        }
    }

//    for(auto i:newx){
//        cout<<i;
//    }cout<<endl;
//    for(auto i:newy){
//        cout<<i;
//    }cout<<endl;

//10
if(newx.size()>60){
    cout<<-1;
    return;
}

cnt=1;

    rep(i,newx.size()-1,0){//0~59
        ansx+=newx[i]*cnt;
        ansy+=newy[i]*cnt;
        cnt*=2;
    }

//cout<<popcount(ansx)<<" "<<popcount(ansy)<<endl;

    cout<<ansx<<" "<<ansy;
}

signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int t=1;
    while(t--)solve();
    return 0;
}

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值