首页 > 其他分享 >AtCoder Beginner Contest 299(E,F)

AtCoder Beginner Contest 299(E,F)

时间:2023-05-27 16:44:22浏览次数:41  
标签:AtCoder Beginner int long define 299 include dp dis

AtCoder Beginner Contest 299(E,F)

E (最短路)

E

题目大意为有\(n\)个点和\(m\)条边,我们我个这些点匹配颜色(有两种颜色),但是要满足下面的条件

必须由一个点的颜色是\(1\)

然后给出\(k\)点限制

对于\(p_i\)这一个点,离他最近的一个颜色为\(1\)的点的最近距离为\(d_i\)

既然知道某个点距离\(1\)的最短路为\(d\),那么从这个点出发最小距离小于\(d\)的点,都一定不能是\(1\),我们可以预先处理出那些点一定是不能是\(1\)的,然后再从这个点出发找,找到一个距离为\(d\)且可以为\(1\)的点,否则找不到,则输出\(-1\)

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <unordered_map>
#include <array>
#include <cstring>
using namespace std;
#define int long long 
#define LL long long
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 1e18
#define INF 1e18
#define mem(a,b) memset((a),(b),sizeof(a))
const int maxn=3e5+10;
const int mod=998244353;
int n,m;
vector<int>g[maxn];
vector<int>color,forbid;
int k;
vector<pair<int,int>>op;
void bfs1(int s,int d)
{
    vector<int>dis(n+1,inf);
    vector<bool>vis(n+1,false);
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
    dis[s]=0;
    q.push({dis[s],s});
    while (!q.empty())
    {
        auto [dd,u]=q.top();
        q.pop();
        if(dd>d) break;
        if(vis[u]) continue;
        vis[u]=true;
        if(dd<d)
        {
            forbid[u]=1;
        }
        for (auto v:g[u])
        {
            if(dis[v]>dis[u]+1)
            {
                dis[v]=dis[u]+1;
                q.push({dis[v],v});
            }
        }
    }
    return ;
}
bool bfs2(int s,int d)
{
    vector<int>dis(n+1,inf);
    vector<bool>vis(n+1,false);
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
    dis[s]=0;
    q.push({dis[s],s});
    while (!q.empty())
    {
        auto [dd,u]=q.top();
        q.pop();
        if(dd>d) break;
        if(dd==d&&!forbid[u])
        {
            color[u]=1;
            return true;
        }
        if(vis[u]) continue;
        vis[u]=true;
        for (auto v:g[u])
        {
            if(dis[v]>dis[u]+1)
            {
                dis[v]=dis[u]+1;
                q.push({dis[v],v});
            }
        }
    }
    return false;
}
signed main ()
{
    cin>>n>>m;
    color.resize(n+1,0);
    forbid.resize(n+1,0);
    for (int i=1;i<=m;i++)
    {
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    cin>>k;
    for (int i=1;i<=k;i++)
    {
        int s,d;
        cin>>s>>d;
        op.push_back({s,d});
        bfs1(s,d);
    }
    bool yes=true;
    for (auto [s,d]:op)
    {
        if(bfs2(s,d))
        {
            continue;
        }
        else 
        {
            yes=false;
            break;
        }
    }
    if(yes)
    {
        cout<<"Yes\n";
        if(k==0) color[1]=1;
        for (int i=1;i<=n;i++)
        {
            cout<<color[i];
        }
        cout<<"\n";
    }
    else 
    {
        cout<<"No\n";
    }
    system ("pause");
    return 0;
}

F(dp,子串)

F

这个题的大意就是给出一个字符串,找到一个非空字符串\(t\),可以得到一个\(s\)为\(tt\),且\(s\)为题目给出的字符串的子串

子串:原来的字符串删除若干个字符

这就代表着\(tt\)里面的字符的顺序只要是符合要求的即可

然后我们可以看到这个\(t\),不断地制造\(t\)

对于一个满足要求的\(tt\),我们需要从原来的字符串里面去找,不如把找\(tt\)转换成在原来的字符串里面找到一前一后一样的子串

对于此时的字符\(now\),此时的位置为\(r\)我们要找到一个\(l\)(这个位置的字符同样是\(now\),是第一个出现该字符的位置,这样就把以\(r\)可以作为\(tt\)的结尾的所有情况都包括了)

我们可以得到一个初状态\(dp[l] [r] =1\),代表着第一个字符串以\(st\)结尾,第二个字符串以\(r\)结尾,前面的都是满足的(初状态只有这一个字符,所以不需要考虑,直接\(dp[l] [r] =1\)

然后我们需要继续深入,往后找后面可以存在的字符,但是后面的前面一个不能超过\(r\)(不然这两个字符串的顺序不是一前一后了,而是相交了),后面不能超过\(n\),

假设\(i,j\)是此时的两个字符串的结尾位置,我们的下一个就在他们位置的后面

假设存在这样一个字符\(k\),\(i\)后面的位置\(nl\)存在,在\(j\)的后面的位置\(nr\)存在

那我们可以得到状态转移方程如下

\[dp[nl][nr]=dp[nl][nr]+dp[i][j] \]

我们取得的答案就是每一个不同结尾,对于此时的位置,只要是结尾的下一个\(now\)字符是\(r\),(这一次刚好是以\(r\)作为界限,\(r\)是第二个的开头,其他的情况,在其他的时候也已经加上了)可以加上这个答案

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <unordered_map>
#include <array>
#include <cstring>
using namespace std;
#define int long long 
#define LL long long
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 1e18
#define INF 1e18
#define mem(a,b) memset((a),(b),sizeof(a))
const int maxn=100+10;
const int mod=998244353;
int n;
string s;
void add(int &x,int c)
{
    x+=c;
    if(x>=mod)
    {
        x-=mod;
    }
    return ;
}
signed main ()
{
    cin>>s;
    n=s.size();
    s=" "+s;
    vector<int>pos(26,-1);
    vector<vector<int>>nxt(n+1);
    for (int i=n;i>=1;i--)
    {
        int now=s[i]-'a';  
        nxt[i]=pos;
        pos[now]=i;
    }
    int ans=0;
    for (int st=2;st<=n;st++)
    {
        int now=s[st]-'a';
        vector<vector<int>>dp(n+1,vector<int>(n+1,0));
        int l=pos[now],r=st;
        dp[l][r]=1;
        for (int i=l;i<r;i++)
        {
            for (int j=r;j<=n;j++)
            {
                for (int k=0;k<26;k++)
                {
                    int nl=nxt[i][k];
                    int nr=nxt[j][k];
                    if(nl==-1||nr==-1||nl>=r) continue;
                   add(dp[nl][nr],dp[i][j]);
                }
            }
        }
        for (int i=l;i<r;i++)
        {
            for (int j=r;j<=n;j++)
            {
                if(nxt[i][now]==r)//如果nxt[i][now]小于r的话,前面可能已经加过一次了,大于更是不可能,我们加的只是此时刚好以r作为界限的情况
                {
                    add(ans,dp[i][j]);
                }
            }
        }
    }
    cout<<ans<<"\n";
    system ("pause");
    return 0;
}

标签:AtCoder,Beginner,int,long,define,299,include,dp,dis
From: https://www.cnblogs.com/righting/p/17436957.html

相关文章

  • Atcoder Grand Contest 062 D - Walk Around Neighborhood
    csy/bxwjz/bx首先将\(a\)排序,如果\(\sum\limits_{i=1}^{n-1}a_i<a_n\)显然就是\(-1\),否则必然有解。先发现一个trivial的事情,就是答案一定位于\([\dfrac{a_n}{2},a_n]\)中,这是因为我们判掉无解的条件之后,我们必然可以用前面的步数走到以\((a_n,0),(0,a_n),(-a_n,0),(......
  • AtCoder Regular Contest 139 E Wazir
    洛谷传送门AtCoder传送门好题。这种题一般可以考虑,观察最优解的性质,对于性质计数。发现如果\(n,m\)均为偶数,可以放满。就是类似这样:#.#.#..#.#.##.#.#..#.#.#因此答案就是\(2\)。如果\(n,m\)有一个为偶数,不妨假设\(n\)为偶数。那么最优解形似:#.#...#..##..#......
  • 【atcoder begin 302】【e题 Isolation 】JAVA的快速输入输出
    importjava.io.*;importjava.util.HashSet;importjava.util.Set;/***@authorfishcanfly*/publicclassMain{publicstaticvoidmain(String[]args)throwsIOException{//BufferedReaderbr=newBufferedReader(newInputStreamReader(......
  • AtCoder Beginner Contest 300(E,F)
    AtCoderBeginnerContest300(E,F)E(概率dp)E这个题意大致就是一开始有一个初始数\(x\)为\(1\),然后我们有一个骰子,最后得到的点数概率一样,为\(\frac{1}{6}\),如果这一次得到的点数为\(i\),那么\(x\)会变成\(i\timesx\),问最后得到数\(n\)的概率为多少先感性的分析一波,对于......
  • AtCoder Regular Contest 146 D >=<
    洛谷传送门AtCoder传送门考虑直接增量构造。把条件拆成形如\(a_u\gex\)时\(a_v\gets\max(a_v,y)\),连边,跑类似一个spfa的东西,就行了。这样一定能构造出一组和最小的解。code//Problem:D->=<//Contest:AtCoder-AtCoderRegularContest146//URL:http......
  • AtCoder Beginner Contest 193 F Zebraness
    洛谷传送门AtCoder传送门复习一下最小割。考虑翻转横纵坐标和为奇数的颜色,那么就变成了,相邻两个格子,相同颜色产生\(1\)的贡献。一眼P4313文理分科。每个格子被分到\(S\)表示染黑,分到\(T\)表示染白。对于每两个相邻格子,建两个虚点,分别表示它们都染黑或者都染白的情况......
  • AtCoder Beginner Contest 302 H. Ball Collector 题解
    AtCoderBeginnerContest302H.BallCollector题意跳过。可以视作将\(a_i,b_i\)之间连了一条边,然后\(a_i,b_i\)之间只能选一个等价于对于一条边只能选择其一个端点。那么对于只包含树的联通块而言,如果都选择儿子节点,那么会有一个根节点无法被选择上;而对于包含至少一个......
  • AtCoder Beginner Contest 302(E,F,G)
    AtCoderBeginnerContest302(E,F,G)E(图,set)E这个题意大致为一开始给出\(n\)个点,没有一条边,后面陆续会有\(q\)次操作,以下两种方式\(1\),输入两个点,代表连接这两个点\(2\),输入一个点,意在把所有和这个点相连的边都删除每一次操作后我的都需要知道操作后还有多少个孤立无援的点(没......
  • AtCoder Regular Contest 132 E Paw
    洛谷传送门AtCoder传送门感觉挺educational的。观察最终形态,发现根据洞分段,有且只有一段没被覆盖,并且左端是向左的脚印,右端是向右的脚印。最终状态就这几种了,直接枚举,概率乘贡献即可。发现左端和右端不影响到对方是对称的,直接求出一边的概率。设\(f_i\)为\(i\)个洞,填......
  • AtCoder Regular Contest 132 F Takahashi The Strongest
    洛谷传送门AtCoder传送门没见过这种在新运算下做卷积的题,感觉挺新奇的。考虑Takahashi成为绝对赢家的必要条件,发现前提是Aoki和Snuke出的要相同。不妨将每种策略映射到一个四进制数(\(P\to1,R\to2,S\to3\)),定义运算\(x\otimesy=\begin{cases}x&x=y\\0......