AtCoder Beginner Contest 418 (A - E)

A - I'm a teapot

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){
    int n;
    cin>>n;
	
    string s;
    
    for(int i=1;i<=n;i++){
        char ch;
        cin>>ch;
        if(i>n-3){

            s.push_back(ch);
        }
    }


    if(s=="tea"){
        cout<<"Yes\n";
    }
    else{
        cout<<"No\n";
    }
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    // cin>>ct;
    while(ct--){
        solve();
    }
    return 0;
}

B - You're a teapot

暴力枚举每一对 \(l,r\) 即可可以用前缀和维护快速得到一段区间内部 t 的数量

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

void solve(){
	string s;
    cin>>s;
    int n=s.size();

    s=" "+s;

    vector<int> a(n+1),pre(n+1);
    for(int i=1;i<=n;i++){
        a[i]=(s[i]=='t');
        pre[i]=pre[i-1]+a[i];
    }

    double ans=0;

    for(int i=1;i<=n;i++){
        for(int j=i+2;j<=n;j++){
            if(!a[i] || !a[j]) continue;
            double tmp=(pre[j]-pre[i-1])-2;
            tmp/=(double)(j-i+1)-2;
            ans=max(ans,tmp);
        }
    }
    printf("%.11lf",ans);
}

signed main(){
    // ios::sync_with_stdio(0);
    // cin.tie(0);

    int ct=1;
    // cin>>ct;
    while(ct--){
        solve();
    }
    return 0;
}

C - Flush

先排序,所有比 \(b\) 小的数都可以全部选完,所有比 \(b\) 大的数都可以选 \(b-1\) 个,此时再从比 \(b\) 大的数中任选一个,这个茶包的数量恰好是 \(b\)。排序后二分即可

如果 \(b>a[n]\) 则不可获胜

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

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

    vector<int> a(n+1),pre(n+1);
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }

    sort(a.begin()+1,a.end());

    for(int i=1;i<=n;i++){
        pre[i]=a[i]+pre[i-1];
    }

    while(q--){
        int x;
        cin>>x;
        if(x>a[n]){
            cout<<-1<<endl;
            continue;
        }

        int pos=lower_bound(a.begin()+1,a.end(),x)-a.begin();
        pos--;
        //第一个小于x的位置
        int ans=pre[pos];
        ans+=1+(n-pos)*(x-1);
        cout<<ans<<endl;
    }
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    // cin>>ct;
    while(ct--){
        solve();
    }
    return 0;
}

D - XNOR Operation

前置知识:如果区间长度为奇数,则区间 \(XNOR\) 等于 \(XOR\),否则等于 \(XOR\) 按位取反

所以对每个区间右端点 \(r\):

  1. 要找到有多少个左端点满足长度是奇数且区间异或和为 \(1\)

  2. 要找到有多少个左端点满足长度是偶数且区间异或和为 \(0\)

\(f[i] [j]\) 表示在奇数位置(\(i==1\))/ 偶数位置(\(i==0\))且前缀异或和为 \(j\) 的数量

当到位置 \(r\)

情况 \(1\),区间长度是奇数,$XOR(l,r)=prexor[r] ~~~ XOR ~~~ prexor[l-1] $

\(prexor[l-1]\) 的值和 \(prexor[r]\) 的值不同(值不同所以异或值为1)

同时因为区间长度是奇数,所以 \(l,r\) 奇偶性相同,所以 \(l-1,r\) 奇偶性不同

所以此时符合条件的 \(l\) 个数即为 $f[ (i ~ and ~ 1) ~ xor ~1] [pre[i]~ xor ~ 1] $

\((i ~ and ~ 1) ~ xor ~1\) 表示与 \(r\) 奇偶性不同的位置,\(pre[i]~ xor ~ 1\) 表示与 \(prexor[r]\) 前缀异或和值不同

情况 \(2\) 同理,符合条件的 \(l\) 个数为 $f[i ~ and ~ 1] [pre[i]] $

这种写法理解起来比较复杂,推荐 DP 写法,简单粗暴

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

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

    vector<int> a(n+1),pre(n+1);
    for(int i=1;i<=n;i++){
        a[i]=(s[i-1]=='1');
        pre[i]=a[i]^pre[i-1];
    }

    int ans=0;
    int cnt[2][2];
    memset(cnt,0,sizeof cnt);

    cnt[0][0]++;

    for(int i=1;i<=n;i++){
        int p=i&1;
    
        ans+=cnt[p][pre[i]];
        ans+=cnt[p^1][pre[i]^1];
        cnt[i&1][pre[i]]++; 
    }

    cout<<ans<<endl;
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    // cin>>ct;
    while(ct--){
        solve();
    }
    return 0;
}

E - Trapezium

不存在三点共线,所以梯形的数量即为两两平行的线段数量

但平行四边形会被计算两次,所以还要减掉一次平行四边形的数量

对于平行线段,维护线段斜率即可

对于平行四边形,如果两个对角线的中点重合,则可以构成一个平行四边形,所以维护线段中点即可

注意维护时使用 \(map\) 会超时,需要用 \(vector + sort\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using pdd=pair<double,double>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;

//返回斜率对应的pii
pii get(pii a,pii b){
    int x=a.second-b.second, y=a.first-b.first;
    
    if(x==0){
        return {0,1};
    }
    if(y==0){
        return {1,0};
    }

    int g=__gcd(abs(x),abs(y));
    x/=g,y/=g;

    if(x<0){
        x=-x;
        y=-y;
    }
    return {x,y};
}

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

    vector<pii> a(n+1);
    for(int i=1;i<=n;i++){
        cin>>a[i].first>>a[i].second;
    }

    int ans=0;
    vector<pii> mp,cnt;

    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            pii k=get(a[i],a[j]);
            mp.push_back(k);

            int x=(a[i].first+a[j].first);
            int y=(a[i].second+a[j].second);

            cnt.push_back({x,y});
        }
    }

    sort(mp.begin(),mp.end());
    sort(cnt.begin(),cnt.end());

    pii t={-inf,-inf};
    int now=-1;

    for(auto p:mp){
        if(p==t) now++;
        else{
            if(now==-1){
                now=1;
                t=p;
            }
            else{
                ans+=(now)*(now-1)/2;
                now=1;
                t=p;
            }
        }
    }
    if(now>0) ans+=(now)*(now-1)/2;

    t={-inf,-inf};
    now=-1;

    for(auto p:cnt){
        if(p==t) now++;
        else{
            if(now==-1){
                now=1;
                t=p;
            }
            else{
                ans-=(now)*(now-1)/2;
                now=1;
                t=p;
            }
        }
    }
    if(now>0) ans-=(now)*(now-1)/2;


    cout<<ans<<endl;
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int ct=1;
    // cin>>ct;
    while(ct--){
        solve();
    }
    return 0;
}
posted @ 2025-08-12 22:17  LYET  阅读(17)  评论(0)    收藏  举报