首页 > 其他分享 >AtCoder Beginner Contest 291(Sponsored by TOYOTA SYSTEMS)(D,E,F)

AtCoder Beginner Contest 291(Sponsored by TOYOTA SYSTEMS)(D,E,F)

时间:2023-03-01 23:55:06浏览次数:51  
标签:AtCoder Beginner Contest int long maxn include dp mod

AtCoder Beginner Contest 291(Sponsored by TOYOTA SYSTEMS)(D,E,F)

D

D

又一次误解题意

这个题的要求是相邻的两个数不同,而我的翻译上是整个数列的数都是不同的 (ಥ﹏ಥ)

大意是给你\(2n\)个数,每一个数都有一个选择,但是我们必须要从这两个数中选择一个,然后我们要求知道有多少种选择满足相邻两个数之间是不同的数量

如果没有误解题意,那么这道题就是很明显的\(dp\)

我们可以这样构造

\(dp[i] [0]\)是长度为\(i\),其中最后一个(也就是第\(i\)个数是第一个数)的数量

\(dp[i] [1]\)是长度为\(i\),其中最后一个(也就是第\(i\)个数是第二个数)的数量

然后我们可得状态转移方程如下

       if (a[i][0]!=a[i-1][0])
        {
            dp[i][0]=(dp[i][0]+dp[i-1][0])%mod;
        }
        if (a[i][0]!=a[i-1][1])
        {
            dp[i][0]=(dp[i][0]+dp[i-1][1])%mod;
        }
        if (a[i][1]!=a[i-1][0])
        {
            dp[i][1]=(dp[i][1]+dp[i-1][0])%mod;
        }
        if (a[i][1]!=a[i-1][1])
        {
            dp[i][1]=(dp[i][1]+dp[i-1][1])%mod;
        }

还蛮好理解的

然后就可以写代码了

#include <iostream>
#include <string>
using namespace std;
const int maxn=2e5+10;
const int mod=998244353;
#define int long long
int n;
int a[maxn][2],dp[maxn][2];
signed main ()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i][0]>>a[i][1];
    }
    dp[1][0]=dp[1][1]=1;
    for (int i=2;i<=n;i++)
    {
        if (a[i][0]!=a[i-1][0])
        {
            dp[i][0]=(dp[i][0]+dp[i-1][0])%mod;
        }
        if (a[i][0]!=a[i-1][1])
        {
            dp[i][0]=(dp[i][0]+dp[i-1][1])%mod;
        }
        if (a[i][1]!=a[i-1][0])
        {
            dp[i][1]=(dp[i][1]+dp[i-1][0])%mod;
        }
        if (a[i][1]!=a[i-1][1])
        {
            dp[i][1]=(dp[i][1]+dp[i-1][1])%mod;
        }
        //cout<<dp[i][0]<<" "<<dp[i][1]<<'\n';
    }
    int ans=(dp[n][1]+dp[n][0])%mod;
    cout<<ans<<'\n';
    system ("pause");
    return 0;
}

E

E

题目大意就是会给我们\(1\)到\(n\)(不是顺序的)\(n\)个数,并且给出\(m\)种关系,如给出\(x\)和\(y\),意思就是\(a_x < a_y\),我们最终的要求是判断是否可以得到唯一的满足条件的数组

对于每两个数之间的关系,我们可以把这个关系看成是两个点之间的边,然后还需要的值每一个点的值,这个我们可以使用拓扑排序(但是要满足这个序列是唯一的,所以在进行拓扑排序时的队列里面的\(size\)要为\(1\),因为此时的值只能赋给一个点)

然后就没什么了

#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
int n,m;
int main ()
{
    cin>>n>>m;
    vector<vector<int>>g(n+1);
    vector<int>in(n+1);
    for (int i=1;i<=m;i++)
    {
        int x,y;
        cin>>x>>y;
        g[x].push_back(y);
        in[y]++;
    }
    vector<int>ans(n+1);
    queue<int>q;
    int cnt=0;
    for (int i=1;i<=n;i++)
    {
        if (!in[i])q.push(i);
    }
    while (!q.empty())
    {
        if (q.size()!=1)//可以赋给多个点,不唯一
        {
            cout<<"No\n";
            system ("pause");
            return 0;
        }
        int u=q.front();
        q.pop();
        ans[u]=++cnt;
        for (auto v:g[u])
        {
            in[v]--;
            if (in[v]==0) q.push(v);
        }
    }
    cout<<"Yes\n";
    for (int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
    cout<<'\n';
    system ("pause");
    return 0;
}

F

F

这个题大意是给你\(n\)个点,然后对于哪两个点之间可连通的判断条件如下

对于\(i\)点和\(j\)点,如果第\(i\)个字符串的第\(j-i\)个字符是\(1\)的,并且\(1<(j-i)<=m\)的情况下,这两点才表明是连通的

然后我们还有\(n-2\)个问题,每次询问对于\(2,3,...n-1\)这些点中的一个点不可以到达的情况下从\(1\)到\(n\)的最小步数

然后看到这一道题,我就觉得和寒假训练营的某一道题相似

题目

这次训练营因为一些原因没有写题解,这两个题都用到了这一个思路

然后其他的就是一些细节的处理,具体的看代码吧

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
#define int long long 
#define inf (int)1e9+10
const int maxn=2e5+10;
int n,m;
signed main ()
{
    cin>>n>>m;
    vector<string>s(n+1);
    for (int i=1;i<=n;i++)
    {
        cin>>s[i];
        s[i]=" "+s[i];
    }
    vector<int>dp0(n+1,inf),dp1(n+1,inf);//dp0[i]代表顺方向的,从1到i的步数,dp1[i]代表从n到i,逆着走
    dp0[1]=0;
    for (int i=1;i<=n;i++)//i作为开始的点
    {
        for (int j=i+1;j<=min(n,i+m);j++)//j作为到达的点
        {
            if (s[i][j-i]=='1')
            {
                dp0[j]=min(dp0[j],dp0[i]+1);
            }
        }
    }
    dp1[n]=0;
    for (int j=n;j>=1;j--)//逆着走时,j是初始点
    {
        for (int i=max(1ll,j-m);i<j;i++)//到达点
        {
            if (s[i][j-i]=='1') dp1[i]=min(dp1[i],dp1[j]+1);
        }
    }
    for (int k=2;k<n;k++)
    {
        int ans=inf;
        for (int i=max(k-m+1,1ll);i<k;i++)
        {
            for (int j=k+1;j<=min(n,i+m);j++)//注意这里的j取min(n,i+m)意思是在不大于n的情况下,我们最远到达的是和i距离为m的点,而不是k-1+m,看到有一些题解时这么写的,一直没找到这个bug
            {
                if (s[i][j-i]=='1')
                {
                    ans=min(ans,dp0[i]+dp1[j]+1);
                }
            }
        }
        if (ans==inf) ans=-1;
        cout<<ans<<' ';
    }
    cout<<'\n';
    system ("pause");
    return 0;
}

标签:AtCoder,Beginner,Contest,int,long,maxn,include,dp,mod
From: https://www.cnblogs.com/righting/p/17170409.html

相关文章

  • AtCoder Beginner Contest 275 A-F 题解
    比赛链接砳赫賏,看懂扣1(A-FindTakahashi模拟。#include<cstdio>#include<algorithm>usingnamespacestd;intn,mx,id=1;intmain(){ intx; scanf("%d......
  • Atcoder ARC084D Small Multiple
    \(O(k)/O(k)\)解法标签:建图最短路考虑对于一个数\(x\),考虑由它在末尾改变能产生哪些状态:\(x+1\),此时对应的数位和\(+1\)\(x\times10\),对应数位和不变那直接把......
  • [AtCoder Grand Contest 060][C. Large Heap]
    看了几篇题解都是从下往上(子树大小从小到大)推的,来整一个从上往下的。题目链接:C-LargeHeap题目大意:称一个大小为\(2^N-1\)的排列是好排列当且仅当其满足对任意\(1\l......
  • AtCoder Beginner Contest 280 A-F 题解
    比赛链接A-PawnonaGrid模拟。#include<cstdio>#include<algorithm>#include<cstring>usingnamespacestd;constintN=15;intn,m,ans;chars[N];i......
  • AtCoder Beginner Contest 279 A-E 题解
    比赛链接A-wwwvvvvvv直接模拟#include<cstdio>#include<cstring>constintN=105;intn,ans;chars[N];intmain(){ scanf("%s",s+1); for(inti=1......
  • AtCoder Beginner Contest 291 A-F 题解
    。。。比赛链接A-camelCase直接循环判断。#include<cstdio>#include<cstring>constintN=20;chars[N];intmain(){ scanf("%s",s+1); for(inti=1;......
  • 一切都与进制有关【USACO 2015 January Contest Bronze】
    一切都与进制有关奶牛贝茜一直在她的牛栏中学习计算机课,最近她在致力于学习不同进制下的数字表示。回想一下,B进制数字的数位从右到左依次代表1,B,B2,B3等等。例如,在......
  • Atcoder试题乱做 Part8
    我喜欢这样跟着你,随便你带我到哪里.\(\text{[ABC231H]MinimumColoring}\)\(\color{green}{\text{[EASY]}}\)显然的行列二分图模型,一个可以染色的格子对应一个权值为......
  • Atcoder ABC 291
    AtcoderABC291D题意n张牌,每张牌两面都有数字,可以翻面,问有多少种情况使得这n张牌中每相邻两张牌表面上的数互不相同思路线性dp,每次比较当前位和上一位是否相同即可......
  • AtCoder Beginner Contest 291
    比赛链接A-camelCase题目大意给一个由英文字母构成的字符串\(S\),\(S\)中只有一个大写字母,输出该大写字母是字符串中第几个字母。题目思路遍历字符串找出大写字母......