AtCoder Beginner Contest 338

ABC338 总结

AtCoder Beginner Contest 338

A - Capitalized?

翻译

给你一个由大写和小写英文字母组成的非空字符串 S。请判断是否满足以下条件:

  • S 的第一个字符是大写字母,其他所有字符都是小写字母。

如果满足,输出 Yes,否则输出 No

分析

按题目说的判断即可。

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;

int n,m,t,a[N];

int main ()
{
    string s;
    cin>>s;
    int st=1;
    if(!(s[0]>='A'&&s[0]<='Z')) st=0;
    for(int i=1;i<s.size();i++) if(!(s[i]>='a'&&s[i]<='z')) st=0;
    if(st) cout<<"Yes";
    else cout<<"No";
    return 0;
}

B - Frequency

翻译

给你一个由小写英文字母组成的字符串 S。请找出在 S 中出现频率最高的字符。如果存在多个这样的字符,请输出按字母顺序排列最早的那个。

分析

用一个桶来计数,然后按字母顺序比较大小即可。

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;

int n,m,t,a[N];

int main ()
{
    string s;
    cin>>s;
    for(int i=0;i<s.size();i++)
    {
        int id=s[i]-'a'+1;
        a[id]++;
    }
    int maxx=0,ans;
    for(int i=1;i<=26;i++)
    {
        if(a[i]>maxx) 
        {
            maxx=a[i];
            ans='a'+i-1;
        }
    }
    cout<<(char)ans;
    return 0;
}

C - Leftover Recipes

翻译

你的冰箱里有 N 种配料。我们称它们为配料 1 和配料 N。您有 Qi 克配料 i

您可以制作两种菜肴。制作一份 A 菜肴,需要 Ai 克配料 i (1iN)。制作一份 B 菜肴,需要 Bi 克配料 i (1iN)。每种菜肴只能做整数份。

输出最多总共可以制作多少份菜肴。

  • 1N10
  • 1Qi106
  • 0Ai106
  • There is an i such that Ai1.
  • 0Bi106
  • There is an i such that Bi1.
  • All input values are integers.

分析

设有做 x 份 A 菜和 y 份 B 菜,可知 x×Ai+y×Bi<=Qi (1iN)xy 最大为 1e6,同时枚举的话一定会超时。可以运用数学解二元方程的思想,先确定 x,再考虑 y

注意不要出现除以零的情况。

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6;

ll n,m,t,q[20],a[20],b[20];

int main ()
{
    cin>>n;
    ll xm=0;
    for(int i=1;i<=n;i++) cin>>q[i],xm=max(xm,q[i]);
    for(int i=1;i<=n;i++) 
    {
        cin>>a[i];
        if(a[i]) xm=min(xm,q[i]/a[i]);
    }
    for(int i=1;i<=n;i++) cin>>b[i];
    ll ans=0;
    for(int x=0;x<=xm;x++)
    {
        ll y=N;
        for(int i=1;i<=n;i++) 
        {
            if(q[i]<a[i]*x) 
            {
                y=-N;
                break;
            }
            else if(b[i]) y=min(y,(q[i]-a[i]*x)/b[i]);
        }
        ans=max(ans,x+y);
    }
    printf("%lld",ans);
    return 0;
}

D - Island Tour

翻译

Atcoder 国里有 n 个小岛,第 i 个岛(1i<n)和第 i+1 个岛有一座桥连接,第 1 个岛和第 n 个岛有桥连接。
你想按照 s1,s2,s3,sm 的顺序依次游览 m 座岛。只能通过桥从一个岛到另一个岛。
但现需要断开一座桥。问你任意选择一座桥断开的情况下,完成游览最少要通过多少次桥。
如果一座桥被多次计算,需要重复计算次数。

抽象化:有 n 个节点,第 i 号节点与第 i+1 号节点相连 (1i<n),第 n 号节点与第 1 号节点相连组成一个环,边为双向边且长度为 1。下面给出一条路径,依次经过 s1,s2,s3smm 个点,求删去一条边后最短路径的长度为多少。

分析

可以分开考虑,只考虑从一点到另一点。由于是环,从一点到另一点只有两条路,要不顺时针,要不逆时针。

例如从 25,写一个函数求 25 的顺时针的距离,那么反过来 52 的顺时针距离就是 25 的时针的距离。要注意从序号小的点到序号大的点和从序号大的点到序号小的点的区别。

接下来记录各边断开后走另一条路的长度,作为对答案的贡献。不过不能将环遍历一遍计算答案,复杂度就是 O(nm),直接爆炸。可以用差分的方式优化,是的,环上做差分。从序号小的点到序号大的点没有不同,但从序号大的点到序号小的点就有区别。

在数组上表现就是如此:

最后计算答案就好了。

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll inf=LONG_LONG_MAX;
ll n,m,t,a[N],w[N];

ll dis(int x,int y)//x->y顺时针距离
{
    return (x<=y) ? (y-x) :(y-x+n);
}
void count(int x,int y,ll v)//v表示如果断了走另一条的距离,x->y顺时针
{
    if(x<=y) 
    {
        w[x]+=v;
        w[y]-=v;
    }
    else 
    {
        w[x]+=v;
        w[n+1]-=v;
        w[0]+=v;
        w[y]-=v;
    }
}
int main ()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++) cin>>a[i];
    for(int i=1;i<m;i++)
    {
        count(a[i],a[i+1],dis(a[i+1],a[i]));
        count(a[i+1],a[i],dis(a[i],a[i+1]));
    }
    ll ans=inf;
    for(int i=1;i<=n;i++)
    {
        w[i]+=w[i-1];
        ans=min(ans,w[i]);
    }
    printf("%lld\n",ans);
    return 0;
}

posted @   zhouruoheng  阅读(30)  评论(1编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示