首页 > 其他分享 >AtCoder Beginner Contest 359

AtCoder Beginner Contest 359

时间:2024-07-06 19:57:41浏览次数:12  
标签:AtCoder le Beginner int sum long sqrt include 359

AtCoder Beginner Contest 359

A - Count Takahashi

有\(n\)个字符串,每个串要么是Takahashi要么是Aoki,问有多少个字符串是Takahashi

额....这还要有题解吗(?)

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
    string a;
    int n,ans=0;
    cin>>n;
    for(int i=1;i<=n;++i)
    {
        cin>>a;
        if(a=="Takahashi")++ans;
    }
    cout<<ans<<endl;
}

B - Couples

有\(2N\)个数,第\(i\)个数是\(A_i\),其中\(1-N\)的每个数恰好会出现两次。问有多少个\(i\)满足\(A_{i-1}=A_{i+1}\)。

翻译把题目唯一要转弯的地方直接翻译过来了,不过好像也没得差。

#include<iostream>
using namespace std;
int n,a[205],ans;
int main()
{
    cin>>n;
    for(int i=1;i<=n+n;++i)
        cin>>a[i];
    for(int i=2;i<n+n;++i)
        if(a[i-1]==a[i+1])
            ++ans;
    cout<<ans<<endl;
    return 0;
}   

C - Tile Distance 2

坐标轴被\(2\times 1\)的方块铺满。给出如下两个定义:

  • 假设坐标对\((i,j)\),那么\(A_{ij}=\{(x,y)|i\le x\le i+1 \& j\le y\le j+1\}\)
  • 如果\(i+j\)是偶数,那么\(A_{i,j}\)和\(A_{i+1,j}\)被同一块方块铺满。
    现在从\((S_x+0.5,S_y+0.5)\)位置开始,希望走到\((T_x+0.5,T_y+0.5)\),问最少要穿过几个方块。

首先沿着\(y\)轴走,每一步必定要穿过一个方块。
而沿着\(x\)轴方向走,每两步必定穿过一个方块。但是可以通过朝着\(y\)方向走,可以让自己一直不跨过方块。

因此,若沿着\(y\)方向次数多于\(x\)的次数,则可以通过朝\(y\)轴移动来避免在\(x\)轴跨方块;否则有几次\(y\)轴移动就可以使得同等次数的\(x\)轴移动不需要跨方块。

这样计算一下还有几次多出来的\(x\)轴移动,然后计算一下要跨过几个方块即可。

#include<iostream>
#include<cstdio>
using namespace std;
long long sx,sy,tx,ty,ans;
int main()
{
    cin>>sx>>sy>>tx>>ty;
    if(sx>tx)swap(sx,tx),swap(sy,ty);
    long long dx=abs(sx-tx),dy=abs(sy-ty);
    long long bx=((((sx+sy)&1)?1:0)+(((tx+ty)&1)?-1:0)+dx);
    ans=max(0ll,(bx-dy)>>1)+dy;
    cout<<ans<<endl;
    return 0;
}   

D - Avoid K Palindrome

给定一个长度为\(N\)的字符串\(S\),包含AB?。同时还给出了一个数字\(K\)。
?可以随意填入AB,问有多少个可能的串\(S\),使得\(S\)的任意一个长度为\(K\)的子串都不是回文串。

发现\(K\)很小,所以直接状压前\(K\)位的状态即可。设\(f[i][S]\)表示当前考虑到了第\(i\)位,前\(K\)位的状态是\(S\)的方案数。转移应该很简单,枚举当前位填什么就好了,然后判断\(S\)是否回文即可。

时间复杂度\(O(n2^k)\)

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MOD=998244353;
int n,k;
string S;
bool pre[1<<10];
int f[1005][1<<10];
void add(int &x,int y){x=(x+y)%MOD;}
int main()
{
    cin>>n>>k;
    cin>>S;
    for(int i=0;i<(1<<k);++i)
    {
        bool flag=true;
        for(int j=0;j<(k>>1);++j)
            if(((i>>j)&1)^((i>>(k-j-1))&1))
                flag=false;
        pre[i]=flag;
    }
    int full=(1<<k)-1;
    f[0][0]=1;
    for(int i=1;i<=n;++i)
    {
        char c=S[i-1];
        for(int j=0;j<(1<<k);++j)
        {
            if(!f[i-1][j])continue;
            if(i>k&&pre[j])continue;
            if(c=='A'||c=='?')
                add(f[i][(j<<1)&full],f[i-1][j]);
            if(c=='B'||c=='?')
                add(f[i][(j<<1|1)&full],f[i-1][j]);
        }
    }
    int ans=0;
    for(int i=0;i<(1<<k);++i)
        if(!pre[i])add(ans,f[n][i]);
    cout<<ans<<endl;
    return 0;
}

E - Water Tank

有一排水槽,编号\(0-n\)。\(1-n\)每个水槽左侧有一个隔板,给出隔板高度,0号水槽左侧可以认为有一个无限高的隔板。
现在不断地向第\(0\)个水槽注水,回答\(1-n\)每个水槽中第一次有水的时间。

考虑水槽\(i\),显然只需要水的高度能够跨过其左侧的隔板那么就能流进来,而想要跨过左侧隔板的高度,显然只需要考虑更小编号的水槽左侧的隔板中,最靠近的、且高度大于当前隔板的隔板,然后两个隔板之间需要注满水。接下来向前重复这个过程即可。

于是用一个单调队列就可以解决问题了。

#include<iostream>
#include<cstdio>
using namespace std;
const int MAX=200200;
int n,h[MAX],a[MAX],t;
long long sum=0;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d",&h[i]);
    h[0]=1000000001;
    a[t=1]=0;
    for(int i=1;i<=n;++i)
    {
        while(h[a[t]]<=h[i])sum-=1ll*h[a[t]]*(a[t]-a[t-1]),--t;
        sum+=1ll*(i-a[t])*h[i];
        a[++t]=i;
        printf("%lld ",sum+1);
    }
    puts("");
    return 0;
}

F - Tree Degree Optimization

有\(n\)个点,每个点有一个权值\(a[i]\)。现在需要把他们连成一棵树。
一个树的代价是\(\sum_{i=1}^n a[i]*d_i^2\),其中\(d_i\)表示节点\(i\)在树上的度数。
求最小代价。

先把权值排序,然后依次加入,每次找一个父亲节点插入到树中。
显然只会插入到插入后权值增量最小的父亲节点。用一个优先队列即可解决。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int MAX=200200;
int n;
int a[MAX];
long long ans;
struct Node{int a,d;long long del;};
bool operator<(Node a,Node b)
{
    if(a.del!=b.del)return a.del>b.del;
    else return a.a>b.a;
}
priority_queue<Node> Q;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    sort(&a[1],&a[n+1]);
    Q.push((Node){a[1],0,a[1]});
    for(int i=2;i<=n;++i)
    {
        Node x=Q.top();Q.pop();
        ans+=x.del+a[i];
        x.d+=1;
        x.del=(1ll*(x.d+1)*(x.d+1)-1ll*x.d*x.d)*x.a;
        Q.push(x);
        Q.push((Node){a[i],1,3ll*a[i]});
    }
    printf("%lld\n",ans);
    return 0;
}

G - Sum of Tree Distance

给一个\(n\)个节点的树,每个节点有一个权值\(a[i]\)。定义\(f(i,j)\):如果\(a[i]\neq a[j]\)则\(f(i,j)=0\);否则\(f(i,j)\)为\(i,j\)在树上的距离。
求\(\sum_{i=1}^n\sum_{j=i+1}^n f(i,j)\)。

这个数据范围非常能分块。
对于数量大于\(\sqrt n\)的权值,可以做一遍\(O(n)\)的\(dp\)。总复杂度为\(O(n\sqrt n)\)。
对于数量小于\(\sqrt n\)的权值,可以暴力两两之间计算。具体的说,考虑\(\sum_{i=1}^k s_i\le n\),且\(s_i\le \sqrt n\)。于是\(\sum_{i=1}^k s_i^2\le \sum_{i=1}^k s_i\sqrt n\le \sqrt n\sum_{i=1}^k s_i\le n\sqrt n\)。
所以这部分暴力求距离的次数也不会超过\(O(n\sqrt n)\)。

如果采用\(O(n\log n)\)的在线LCA求法的话,可以做到\(O(n\sqrt n\log n)\),实际上远远不满。或者采用\(O(1)\)求LCA的方法,欧拉序+ST表,最终复杂度能做到\(O(n\sqrt n)\)。

如果不分块的就可以点分治随便弄弄,好像不是很难。

标签:AtCoder,le,Beginner,int,sum,long,sqrt,include,359
From: https://www.cnblogs.com/cjyyb/p/18287659

相关文章

  • Solution - Atcoder AGC010E Rearranging
    因为只有相邻的互质的\(a_i\)可以交换,那么就说明不互质的\(a_i\)无法相交换,对应的位置关系也就不会改变。于是可以考虑图论建模,对于\(\gcd(a_i,a_j)>1\),连边\((i,j)\)。那么对于先手,就相当于要把这些边定向,变为一个DAG。而后手因为要保证最大,所以肯定是在DAG上跑......
  • AtCoder Beginner Contest 359
    AtCoderBeginnerContest359这场我赛时打的非常不好,只做出了\(2\)题。A-CountTakahashi签到//Problem:A-CountTakahashi//Contest:AtCoder-UNIQUEVISIONProgrammingContest2024Summer(AtCoderBeginnerContest359)//URL:https://atcoder.jp/conte......
  • Solution - Atcoder AGC034F RNG and XOR
    考虑到这个边权是\(\oplus\),那么说明对于\((u,v)\),\(u\tov\)和\(v\tou\)的边权实质是相同的。那么对于\(0\tox\),就可以反过来,记录下对应的路径,从\(x\)开始走,那么第一次走到\(0\)的时候也就是从\(0\)第一次走到\(x\)的时候。于是就转化为了\(x\)为起点,第一次......
  • AtCoder Beginner Contest 043
    D-Unbalanced只需要找到形如\(XX\)、\(XYX\)的字串即可。即两个相同字符之间最多间隔一个字符。证明:若不然,\(AXYA\),每加一个字符\(A\),都要增加多余字符\(XY\),不可能符合要求。#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;intmain(){ ios......
  • AtCoder Beginner Contest 042
    C-Iroha'sObsession用一个\(\rmst\)数组把每一位标记,然后枚举大于\(n\)的数,一旦有各位都满足要求的数出现就\(\rmbreak\)。#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;boolst[10];boolcheck(intx){ while(x){ intb=x%1......
  • Atcoder ABC091D Two Sequences
    首先根据\(\operatorname{xor}\),就想到拆成二进制的\(a_{i,w},b_{i,w}\)来处理。类似竖式加法,考虑把得到的结果\(c_{w}\)分为\(a_{i,w}+b_{j,w}+x\),其中\(x\)就是上一位的进位。进一步的,发现对于总的\(c_{w}\),\(a_{i,w},b_{j,w}\)肯定都在这个位置加了\(......
  • Atcoder ARC090F Number of Digits
    记\(n\)为题面的\(S\)。能发现对于\(f(l)=8\),共有\(9\times10^7\)个数。此时就已经有\(8\times9\times10^7>10^8=n_{\max}\)了,就说明不存在\(f\ge8\)的情况,还满足这部分对应的数能全被选满。所以可以知道对于\(f(l)\ge8\)的情况,只存在\(f(r)-f(l)=......
  • AtCoder Beginner Contest 359 (A ~F)
    A-CountTakahashiQuestion:给你n个单词,要么是Takahashi,要么是Aoki;输出有几个Takahashi即可。Code:#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'#defineintlonglongtypedeflonglongll;typedefunsignedlonglongull;typedefpair<......
  • Atcoder ABC 360 全题解
    致歉对不起,我不应该在全题解的编写上咕咕咕两个月,导致流量大量流失。我知错了,下次还犯。AB无C考虑一个箱子里的所有球,我们需要把这些球放进互不相同的一些箱子里。然而我们可以留一个球在箱子里,显然留重量最大的最好,所以答案就是$\sum_{i=1}^{N}W_i$减去每个箱子里的最......
  • AtCoder Beginner Contest 360
    A-AHealthyBreakfast(abc360A)题目大意给定一个字符串包含RMS,问R是否在S的左边。解题思路比较R和S的下标,谁小即谁在左边。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){ios::sync_with_stdio(false);......