AT ABC 418

ATcoder ABC418

跳伞


A - I'm a teapot

水题,懒得说。

code
#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef long long ll; 
const int N=1e7+5,mod=998244353;
const int INF=1e9+7; 
const int inf=LONG_LONG_MAX/4;
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int n;
string s;
fuck void solve()
{
    cin>>n>>s;s=' '+s;
    if(n<3){cout<<"No"<<endl;return;}
    if(s[n]=='a'&&s[n-1]=='e'&&s[n-2]=='t')cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
}
signed main() 
{ 
    solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666

B - You're a teapot

暴力枚举两个 $ "t" $ ,然后 $ check $ 一下,$ O(n^{3}) $ 能过,依旧水题。

code
#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef long long ll; 
const int N=1e7+5,mod=998244353;
const int INF=1e9+7; 
const int inf=LONG_LONG_MAX/4;
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int n;
string s;
fuck void solve()
{
    cin>>s;s=' '+s;
    double ans=0.0;
    for(int i=1;i<s.size();i++)
    {
        if(s[i]=='t')
        {
            for(int j=i+1;j<=s.size();j++)
            {
                if(s[j]=='t')
                {
                    int sum=0;
                    for(int k=i;k<=j;k++)
                    {
                        if(s[k]=='t')sum++;
                    }
                    ans=max(ans,1.0*(sum-2)/(j-i-1));
                }
            }
        }
    }
    printf("%.10lf\n",ans);
}
signed main() 
{ 
    solve(); 
    return 0; 
}

C - Flush

开题时被翻译搞懵逼了。

简述题意

一共有 $ n $ 种口味的茶包,对应编号 $ 1~i $ ,第 $ i $ 种口味有 $ a_{i} $ 个。

  • 游戏难度 $ b $ 需要选择一个 $ x(b \leq x \leq \displaystyle \sum_{i=1}^{n}a_{i}) $ ,然后庄家有选择 $ x $ 个茶包给玩家;
  • 玩家需要从 $ x $ 个茶包中选出 $ b $ 个相同的口味的茶包才能获胜;
  • 庄家会尽量选择让玩家无法选出 $ b $ 个相同口味的茶包;
  • 答案要求输出最小的 $ x $ ,如果无解输出 $ -1 $ 。

问题分析

  • 庄家会使每种口味的茶包不超过 $ b-1 $ 个。所以所有口味茶包的最大可能数量总和为 $ S(b)= \displaystyle \sum_{i=1}^{n}min(a_{i},b-1) $ 。
  • 如果 $ x>S(b) $ ,那么无论庄家如何选择必然有一种口味存在 $ b $ 个。

优化查找

  • 首先将茶包 $ a $ 数组排序,并计算前缀和;
  • 对于每一个 $ b $ ,二分查找找到第一个茶包个数大于 $ b-1 $ 的位置 $ pos $ ,于是就可以快速计算 $ S(b)=pre_{pos}+c \times (n-pos) $ 。

时间复杂度:$ O(n \cdot log(n)+ m \cdot log(n))$

code
#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef long long ll; 
const int N=1e7+5,mod=998244353;
const int INF=1e9+7; 
const int inf=LONG_LONG_MAX/4;
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int m,n,sum=0;
int a[N];
int pre[N];
fuck void solve()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        sum+=a[i];
    }
    sort(a,a+n);
    memset(pre,0,sizeof(pre));
    for(int i=0;i<n;i++)pre[i+1]=pre[i]+a[i];
    while(m--)
    {
        int b;cin>>b;
        int c=b-1;
        int pos=upper_bound(a,a+n,c)-a;
        int ans=max(b,pre[pos]+c*(n-pos)+1);
        if(ans<=sum)
        {
            cout<<ans<<endl;
        }
        else cout<<-1<<endl;
    }
}
signed main() 
{ 
    solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666

D - XNOR Operation

分析问题

  • 经过使用神秘的观察法,可以发现这合并操作不就是异或吗?
  • 再通过首烷样例的方法,可以总结出:$ \ $
    1. 如果字符串长度为奇数,最终结果等于所有字符的异或和;
    2. 如果字符串长度为偶数,最终结果等于所有字符异或和再异或上 $ 1 $ ;

处理子串

考虑处理单个子串,根据这里子串定义我们可以采取以下策略优化计算:

  • 使用前缀异或和数组 $ pre $ 计算任意子串的异或和,定义:$ pre_{0}=0,pre_{i}=pre_{0} \bigoplus pre_{1} \bigoplus … \bigoplus pre[i] $ ;
  • 对一个子串 $ [i,j] $ 就可以采用 $ pre_{j} \bigoplus pre_{i-1} $ 快速计算出;
  • 根据子串长度的奇偶性,就可以对条件进行转换:$ \ $
    1. 长度为奇数时:$ pre_{j} \bigoplus pre_{i-1}=1 \rightarrow pre_{j} = pre_{i-1} \bigoplus 1 $ ;
    2. 长度为偶数时:$ pre_{j} \bigoplus pre_{i-1}=0 \rightarrow pre_{j} = pre_{i-1}$ ;
  • 将前缀值按奇偶性分类,计算前缀异或和出现的次数,以便快速计算满足要求的 $ (i,j) $ 对数。

动态计算答案

遍历前缀位置 $ i \in [1,n] $ ,根据 $ i $ 的奇偶性:$ \ $

  • 如果 $ i $ 是奇数,统计前面偶数位置中 $ pre_{j}=pre_{i} $ (长度为偶数)数量和奇数位置中 $ pre_{j}=pre_{i} \bigoplus 1 $ (长度为奇数)的数量;
  • 如果 $ i $ 是偶数,统计前面奇数位置中 $ pre_{j}=pre_{i} $ (长度为偶数)数量和偶数位置中 $ pre_{j}=pre_{i} \bigoplus 1 $ (长度为奇数)的数量;

最后更新一下奇偶异或前缀出现次数。

code
#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef long long ll; 
const int N=1e7+5,mod=998244353;
const int INF=1e9+7; 
const int inf=LONG_LONG_MAX/4;
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int n;
int a[N];
int pre1[3]={1,0};
int pre2[3]={0,0};
fuck void solve()
{
    cin>>n;int ans=0,pre=0;
    string s;cin>>s;s=' '+s;
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='1')pre^=1;
        else pre^=0;
        if(i%2==0)
        {
            ans+=(pre1[pre]+pre2[pre^1]);
            pre1[pre]++;
        }
        else 
        {
            ans+=(pre2[pre]+pre1[pre^1]);
            pre2[pre]++;
        }
    }
    cout<<ans<<endl;
}
signed main() 
{ 
    solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666

E - Trapezium

跳伞

思路

枚举点对计算斜率,对于两条斜率相等的直线必然能形成一个梯形,用map存一下斜率的分子和分母。

然后对于一个平行四边形发现其被重复计算一次,考虑如何计算平行四边形的数量。根据平行四边形的性质,可以推断出如果两个线段的中点相同,那么这两条线段必然可以成为一个平行四边形的对角线,用map维护点对即可,需要使用浮点型。


code

code
#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef long long ll; 
const int N=2e3+5,mod=998244353;
const int INF=1e9+7; 
const int inf=LONG_LONG_MAX/4;
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int n;
map<pair<int,int>,int>mp;
map<pair<double,double>,int>mp1;
#define fr first 
#define se second
fuck pair<int,int> calc(pair<int,int>a,pair<int,int>b)
{
    int tmp1=a.se-b.se;
    int tmp2=a.fr-b.fr;
    // cout<<"ccccccccc"<<endl;
    int g=__gcd(tmp1,tmp2);
    // cout<<"ddddddddddd"<<endl;
    pair<int,int>frz;
    // cout<<g<<" "<<endl;
    frz.fr=tmp1/g;
    frz.se=tmp2/g;
    return frz;
}
pair<int,int>a[N];
fuck void solve()
{
    // cout<<"aaaaaaaaaaaaaaa"<<endl;
    int n;n=read();int ans=0;
    for(int i=1;i<=n;i++)a[i].fr=read(),a[i].se=read();
    // cout<<"bbbbbbbbbbbbbbb"<<endl;
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            ans+=mp[calc(a[i],a[j])];
            mp[calc(a[i],a[j])]++;
        }
    // cout<<ans<<endl;
    // cout<<"ccccccccccccccccccc"<<endl;
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            double tmp1=1.0*(a[i].fr+a[j].fr)/2;
            double tmp2=1.0*(a[i].se+a[j].se)/2;
            // cout<<tmp1<<" "<<tmp2<<" "<<mp1[{tmp1,tmp2}]<<endl;
            ans-=mp1[{tmp1,tmp2}];
            mp1[{tmp1,tmp2}]++;
        }
    cout<<ans<<endl;
}
signed main() 
{ 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    // int QwQ=read();
    // int fuckccf=read();
    // while(QwQ--)solve(); 
    solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666


完结收工!!!!!

个人主页

看完点赞,养成习惯

\(\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\)

posted @ 2025-08-10 10:55  Nightmares_oi  阅读(3)  评论(0)    收藏  举报