AtCoder Beginner Contest 378

AtCoder Beginner Contest 378 总结

A

直接模拟,存 14 出现个数。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=1;
map<int,int> H;
void solve()
{
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    H[a]++,H[b]++,H[c]++,H[d]++;
    int ans=0;
    for(int i=1;i<=4;i++) ans+=H[i]/2;
    cout<<ans<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}


B

要确定 d 处于哪一段区间内,分类讨论一下就能出来。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=105;
int n,m;
ll q[N],r[N];
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>q[i]>>r[i];
    cin>>m;
    while(m--)
    {
        ll t,d;
        cin>>t>>d;
        if(d<=r[t]) cout<<r[t]<<'\n';
        else 
        {
            if((d-r[t])/q[t]*q[t]==d-r[t]) cout<<d<<'\n';
            else cout<<(d-r[t])/q[t]*q[t]+r[t]+q[t]<<'\n';
        }
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}


C

每次更新该值出现的位置,用 map 记录,如果出现了就输出位置,否则输出 1

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
int a[N];
map<ll,int> H;
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(H.count(a[i])) cout<<H[a[i]]<<' ';
        else cout<<-1<<' ';
        H[a[i]]=i;
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}


D

观察数据的范围都很小,直接用 dfs 模拟。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=15;
int n,m,k;
char g[N][N];
bool v[N][N];
int fx[]={0,0,1,-1};
int fy[]={1,-1,0,0};
int dfs(int x,int y,int cnt)
{
    if(cnt==k) return 1;
    int ret=0;
    v[x][y]=1;
    for(int i=0;i<4;i++) 
    {
        int nx=x+fx[i],ny=y+fy[i];
        if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&!v[nx][ny]&&g[nx][ny]=='.') 
            ret+=dfs(nx,ny,cnt+1);
    }
    v[x][y]=0;
    return ret;
}
void solve()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) 
        for(int j=1;j<=m;j++) 
            cin>>g[i][j];
    int ans=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(g[i][j]=='.') 
                ans+=dfs(i,j,0);
    cout<<ans<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}


E

要推一下式子:

Si=(A1+A2++Ai)modM,就有:

1lrN((lirAi)modM)=1lrN(SrSl1)modM

然后因为 0Sl1,Sr<M,所以

(SrSl1)modM=SrSl1+{0(Sl1Sr)M(Sl1>Sr)

这样就去掉了取模。

Xr 为在 S0Sr1 中大于 Sr 的数的个数。所以:

r=1nl=1r(SrSl1)modM=r=1N(Sr×rl=1rSl1+M×Xr).

那么问题就是对于 Xr 的维护,可以用权值线段数组,单调修改,区间查询。
要注意 Si 可以等于 0,所以要么加上偏移量,要么特判一下。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,m;
ll a[N],b[N],c[N];
int lowbit(int x) 
{
    return x&-x;
}
void add(int k,int x)
{
    if(!k) return ;
    for(int i=k;i<=m;i+=lowbit(i)) c[i]+=x;
}
ll query(int k)
{
    ll ret=0;
    for(int i=k;i;i-=lowbit(i)) ret+=c[i];
    return ret;
}
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i],b[i]=b[i-1]+a[i];
    for(int i=1;i<=n;i++) b[i]%=m;
    ll ans=0,s=0;
    for(int i=1;i<=n;i++)
    {
        ans+=b[i]*i-s+(query(m)-query(b[i]))*m;
        s+=b[i];
        add(b[i],1);
    }
    cout<<ans<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}


F

先理解下题意,要满足条件,就是找到两个度数为 2 的点,这两个点的路径上全是度数为 3 的点,将这两个点连接即可。

那么考虑暴力查找,对于每个度数为 2 的点,找到另一个度数为 2 的点,只有下一个点度数为 3 才能走过去。显然这样的做法是 O(n2) 的,也很容易被卡。

再进一步思考,将路径换成两点到最近公共祖先的路劲拼起来,而且最近公共祖先的度数必须是 3。那么就可以枚举所有度数为 3 的点作为根节点,搜索度数为 2 的点的个数 sum,贡献就是 sum×(sum1)/2,标记经过的所有度数为 3 的点,不用重复计算。

复杂度为 O(n)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
vector<int> g[N];
bool v[N];
int dfs(int x,int fa)
{
    int ret=0;
    v[x]=1;
    for(int i=0;i<g[x].size();i++)
    {
        int y=g[x][i];
        if(y==fa) continue;
        if(g[y].size()==2) ret++;
        else if(g[y].size()==3) ret+=dfs(y,x);
    }
    return ret;
}
void solve()
{
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    ll ans=0;
    for(int i=1;i<=n;i++) 
    {
        if(g[i].size()==3&&!v[i])
        {
            ll x=dfs(i,0);
            ans+=x*(x-1)/2;
        }
    }
    cout<<ans<<'\n';
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}

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