【A~G2所有题】-Codeforces Round 964 (Div. 4)

A - A+B Again?

将一个两位数的个位和十位相加即可

#include<iostream>
using namespace std;
int main(){
    int T;cin>>T;
    while(T--){
        int n;cin>>n;
        cout<<n/10+n%10<<endl;
    }
}

B - Card Game

最多只有4种情况,分类判断即可。

#include<iostream>
using namespace std;
int main(){
    int T;cin>>T;
    while(T--){
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        int ans=0;
        if(a>c&&b>=d||a>=c&&b>d) ans+=2;
        if(a>d&&b>=c||a>=d&&b>c) ans+=2;
        cout<<ans<<endl;
    }
}
/*
a c  b d
a d  b c

*/

C - Showering

排序之后首尾相减就能得到空闲的区间。

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
    int T;cin>>T;
    while(T--){
        int n,s,m;
        cin>>n>>s>>m;
        vector<pair<int,int>>v;
        for(int i=1;i<=n;i++){
            int st,ed;cin>>st>>ed;
            v.push_back({st,ed});
        }
        sort(v.begin(),v.end());
        int last=0;
        int f=0;
        for(int i=0;i<v.size();i++){
            if(v[i].first-last>=s){
                f=1;break;
            }else{
                last=v[i].second;
            }
        }
        if(m-last>=s) f=1;
        if(f) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
}

D - Slavic’s Exam

使用一个pos指针首先指向s2的第0个位置
遍历s1,当s1中遇到?时,可以插入当前正在匹配到pos的位置上的字母,
遇到字母时,如果和当前正在匹配到pos2的位置上的字母一样时,让pos向后移动也就是pos++

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
    int T;cin>>T;
    while(T--){
        string s1,s2;cin>>s1>>s2;
        int pos=0;
        for(int i=0;i<s1.length();i++){
            if(s1[i]=='?'){
                if(pos==s2.length()){
                    s1[i]='a';
                }else{
                    s1[i]=s2[pos++];
                }
            }else{
                if(s1[i]==s2[pos]) pos++;
            }
        }
        if(pos==s2.length()){
            cout<<"YES\n"<<s1<<endl;
        }else{
            cout<<"NO\n";
        }
    }
}

E - Triple Operations

预处理、前缀和
首先预处理3的次方的一个数组a
接着预处理前缀和数组pre,使用upper_lower函数查找某个数在a数组中的位置。
预处理完成后再输出,时间复杂度为 O ( 1 ) O(1) O(1)

#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
const int MAXN=2e5+10;
int pre[MAXN],a[20]; ;
signed main(){
    pre[1]=1; a[0]=1;
    for(int i=1;i<20;i++) a[i]=a[i-1]*3;
    for(int i=2;i<MAXN;i++) pre[i]=pre[i-1]+upper_bound(a,a+20,i)-a;
    
    int T;cin>>T;
    while(T--){
        int l,r;cin>>l>>r;
        cout<<pre[l]+pre[r]-pre[l-1]*2<<endl;
    }
}

F - Expected Median

这道题注意快速求解组合数,MOD是一个质数,使用费马小定理求解组合数

#include<iostream>
#define int long long
using namespace std;

const int MOD=1e9+7;
const int N=2e6+10;
int fact[N],infact[N];

int qpow(int a,int b){
    int res=1;
    while(b){
        if(b&1) res=res*a%MOD;
        a=a*a%MOD; b>>=1;
    }
    return res;
}
void ini(){
    fact[0]=infact[0]=1;
    for(int i=1;i<N;i++){
        fact[i]=fact[i-1]*i%MOD;
        infact[i]=qpow(fact[i],MOD-2);
    }
}
int C(int a,int b){
    if(a<b) return 0;
    return fact[a]*infact[b]%MOD*infact[a-b]%MOD;
}

signed main(){
    ini();
    
    

    int T;cin>>T;
    while(T--){
        int n,k;cin>>n>>k;
        int a[n+2];
        int cnt1=0;
        for(int i=1;i<=n;i++) {
            cin>>a[i];if(a[i]) cnt1++;
        }
        int ans=0;
        for(int i=(k+1)/2;i<=min(k,cnt1);i++){
            ans+=(C(cnt1,i)*C(n-cnt1,k-i))%MOD;
            ans%=MOD;
        }
        cout<<ans<<endl;
    }
}

G1 - Ruler (easy version)

l o g 3 999 = 6.28 log_3999=6.28 log3999=6.28 ,题目给出7次机会可以满足三分查找。

对于一个区间 [ l , r ] [l,r] [l,r]来说,将他分为3份,得到 [ l , l + ( r − l ) / 3 ] , [ l + ( r − l ) / 3 , r − ( r − l ) / 3 ] , [ r − ( r − l ) / 3 , r ] [l,l+(r-l)/3],[l+(r-l)/3,r-(r-l)/3],[r-(r-l)/3,r] [l,l+(rl)/3],[l+(rl)/3,r(rl)/3],[r(rl)/3,r],令两个中间的点分别为 l m i d 、 r m i d lmid、rmid lmidrmid

一个目标 x x x在区间 [ l , r ] [l,r] [l,r]上,
假如 l m i d 、 r m i d lmid、rmid lmidrmid都符合合条件,那么缩小区间 r = l m i d r=lmid r=lmid,
假如 l m i d 、 r m i d lmid、rmid lmidrmid都不符合条件,那么缩小区间 l = r m i d l=rmid l=rmid,
假如 l m i d lmid lmid符合, r m i d rmid rmid不符合条件,那么缩小区间 l = l m i d + 1 , r = r m i d − 1 l=lmid+1,r=rmid-1 l=lmid+1,r=rmid1,
不存在 l m i d lmid lmid不符合, r m i d rmid rmid符合条件的情况,因为 l m i d lmid lmid始终在 r m i d rmid rmid左边。

#include<iostream>
#define int long long
using namespace std;
int check(int l,int r){
    cout<<'?'<<' '<<l<<' '<<r<<'\n';
    int res;cin>>res;
    if(l*r==res) return 1;
    if(l*(r+1)==res) return 2;
    if((l+1)*(r+1)==res) return 3;
    return 0;
}
signed main(){
    int T;cin>>T;
    while(T--){
        int l=2,r=999;
        while(l<=r){
            int lmid=l+(r-l)/3;
            int rmid=r-(r-l)/3;
            int res=check(lmid,rmid);
            if(res==1) l=rmid+1;
            else if(res==2) l=lmid+1,r=rmid-1;
            else if(res==3) r=lmid-1;
        }
        cout<<'!'<<' '<<l<<'\n';
    }
}

G2 - Ruler (hard version)

#include<iostream>
#define int long long
using namespace std;
int check(int l,int r){
    cout<<'?'<<' '<<l<<' '<<r<<'\n';
    int res;cin>>res;
    if(l*r==res) return 1;
    if(l*(r+1)==res) return 2;
    if((l+1)*(r+1)==res) return 3;
    return 0;
}
signed main(){
    int T;cin>>T;
    while(T--){
        int l=2,r=999;
        while(l<=r){
            int lmid=l+(r-l)/3;
            int rmid=r-(r-l)/3;
            int res=check(lmid,rmid);
            if(res==1) l=rmid+1;
            else if(res==2) l=lmid+1,r=rmid-1;
            else if(res==3) r=lmid-1;
        }
        cout<<'!'<<' '<<l<<'\n';
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值