Codeforces Round 964 (Div. 4) 补题记录(A~G2)

难绷事实:B wa 一发

A

......

#include<bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
const int N=500100;
int a[N];
signed main(){
    int T;cin>>T;
    while(T--){
        int n;
        cin>>n;
        string s=to_string(n);
        int ss=0;
        for(auto&x:s)ss+=x-'0';
        cout<<ss<<'\n';
    }
    return 0;
} // main

B

直接枚举每一种组合。


#include<bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
const int N=500100;
int a[N];
signed main(){
    int T;cin>>T;
    while(T--){
        int a1,a2,b1,b2;
        cin>>a1>>a2>>b1>>b2;
        int a[]={a1,a2},b[]={b1,b2};
        int cnt=0;
        for(int i=0;i<2;++i)
        for(int j=0;j<2;++j){
            int C=0,CC=0;
            if(a[i]>b[j])++C;
            else if(a[i]<b[j])++CC;
            if(a[i^1]>b[j^1])++C;
            else if(a[i^1]<b[j^1])++CC;
            if(C>CC)++cnt;
        }
        cout<<cnt<<'\n';
    }
    return 0;
} // main

C

直接枚举 \(n\) 个区间和起点、终点之间组成的 \(n+1\) 个空区域,判断它们是否存在一个空区域的大小超过 \(m\) 即可。

时间复杂度为 \(O(n)\)

#include<bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
const int N=500100;
int a[N],l[N],r[N];
signed main(){
    int T;cin>>T;
    while(T--){
        int n,s,m;
        cin>>n>>s>>m;
        for(int i=1;i<=n;++i)cin>>l[i]>>r[i];
        int ok=0;
        if(l[1]>=s)ok=1;
        if(m-r[n]>=s)ok=1;
        for(int i=1;i<n;++i)
            if(l[i+1]-r[i]>=s){ok=1;break;}
        cout<<(ok?"Yes\n":"No\n");
    }
    return 0;
} // main

D

随便贪心。如果当前字符能匹配就直接匹配,否则如果当前字符是 ? 就直接修改为当前需要匹配的字符即可。时间复杂度为 \(O(n)\)

#include<bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
const int N=500100;
int a[N],l[N],r[N];
signed main(){
    int T;cin>>T;
    while(T--){
        string s,t;
        cin>>s>>t;
        int n=s.size(),m=t.size();
        int p=0;
        for(int i=0;i<n;++i){
            if(p<m&&s[i]==t[p])++p;
            else if(p<m&&s[i]=='?'){
                s[i]=t[p];
                ++p;
            }else if(s[i]=='?'){
                s[i]='a';
            }
        }
        if(p==m){
            cout<<"YES\n";
            cout<<s<<'\n';
        }else{
            cout<<"NO\n";
        }
    }
    return 0;
} // main

E

首先先一直减一个数让这个数变为 \(0\),然后用 \(0\) 和另外一个非 \(0\) 数做操作直到所有数都变为 \(0\) 即可。考虑使用前缀和提前算出来每一个前缀需要多少次操作才能全部变成 \(0\)。时间复杂度为 \(O(n)\)

#include<bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
const int N=500100;
int a[N],qu[N],S[N];
signed main(){
    int T;cin>>T;
    for(int i=1;i<N;++i){
        int j=i;
        while(j){
            j/=3;
            ++qu[i];
        }
        S[i]=S[i-1]+qu[i];
    }
    while(T--){
        int l,r;
        cin>>l>>r;
        int cnt=qu[l]+S[r]-S[l-1];
        cout<<cnt<<'\n';
    }
    return 0;
} // main

F

简单组合计数。考虑枚举当前选择的 \(k\) 个数中有多少个数的值为 \(1\)(需要保证 \(1\) 的数量 \(\ge 0\) 的数量)。那么设总共有 \(\text{one}\)\(1\)\(\text{zero}\)\(0\),当前枚举 \(i\)\(1\)\(k-i\)\(0\)。那么一共有 \(\binom{\text{zero}}{i}\binom{\text{one}}{k-i}\) 个不同的方案。全加起来即可。时间复杂度为 \(O(n)\)

#include<bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
const int N=500100,mod=1e9+7;
int a[N],qu[N],S[N];
int fac[N],inv[N],ifac[N];
int binom(int x,int y){
    if(x<y)return 0;
    return fac[x]*ifac[y]%mod*ifac[x-y]%mod;
}
signed main(){
    int T;cin>>T;
    for(int i=0;i<2;++i)fac[i]=inv[i]=ifac[i]=1;
    for(int i=2;i<N;++i){
        fac[i]=fac[i-1]*i%mod;
        inv[i]=mod-inv[mod%i]*(mod/i)%mod;
        ifac[i]=ifac[i-1]*inv[i]%mod;
    }
    while(T--){
        int n,k;
        cin>>n>>k;
        for(int i=1;i<=n;++i)cin>>a[i],S[i]=S[i-1]+a[i];
        int one=S[n],zero=n-S[n];
        int cnt=0;
        for(int i=(k+1)/2;i<=k;++i){
            // meijv you i ge 1, ze you k-i ge 0
            // cout<<"qwq "<<one<<' '<<zero<<' '<<i<<' '<<k-i<<' '<<binom(one,i)<<' '<<binom(zero,i)<<'\n';
            cnt+=binom(one,i)*binom(zero,k-i)%mod;
            cnt%=mod;
        }
        cout<<cnt%mod<<'\n';
    }
    return 0;
} // main

G1

阅读理解题。每一次询问 1 k 若回答为 \(k\) 则往大二分否则往小二分,正好询问 \(10\) 次。

#include<bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
const int N=500100,mod=1e9+7;
int a[N],qu[N],S[N];
int fac[N],inv[N],ifac[N];
int binom(int x,int y){
    if(x<y)return 0;
    return fac[x]*ifac[y]%mod*ifac[x-y]%mod;
}
signed main(){
    int T;cin>>T;
    while(T--){
        int l=2,r=1000,best=1;
        while(l<=r){
            int mid=l+r>>1;
            cout<<"? 1 "<<mid<<endl;
            int x;cin>>x;
            int real=mid;
            if(real==x)best=mid,l=mid+1;
            else r=mid-1;
        }
        cout<<"! "<<best+1<<endl;
    }
    return 0;
} // main

G2

发现每一次询问 1 x 的话浪费了第一个维度,所以考虑充分利用题目给出的信息。对于当前二分到的区间 \([l,r]\),令 \(p_1\)\(p_2\) 为该区间的三等分点,则询问 \(\tt{p_1,p_2}\),得到的答案为 \(x\)

  • \(p_1\times p_2=x\)。则答案区间在 \(p_2\) 的右边。
  • \(p_1\times p_2\neq x\),此时分两种情况讨论:
    • \(p_1\times (p_2+1)=x\)。则答案在 \(p_1\)\(p_2\) 两端点的中间。
    • \(p_1\times (p_2+1)\neq x\),则答案在 \(p_1\) 的左边。

这样正好可以在 \(7\) 次操作中得到答案。

#include<bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
const int N=500100,mod=1e9+7;
int a[N],qu[N],S[N];
int fac[N],inv[N],ifac[N];
int binom(int x,int y){
    if(x<y)return 0;
    return fac[x]*ifac[y]%mod*ifac[x-y]%mod;
}
signed main(){
    int T;cin>>T;
    while(T--){
        int l=2,r=1000,best=1;
        while(l<=r){
            int p1=l+(r-l)/3,p2=r-(r-l)/3;
            cout<<"? "<<p1<<' '<<p2<<endl;
            int area=p1*p2;int x;cin>>x;
            if(x==area)
                best=p2,l=p2+1;
            else if(x==p1*(p2+1))
                best=p1,l=p1+1,r=p2-1;
            else
                r=p1-1;
        }
        cout<<"! "<<best+1<<endl;
    }
    return 0;
} // main
posted @ 2024-08-07 10:28  yhbqwq  阅读(22)  评论(0编辑  收藏  举报