返回顶部

AtCoder Beginner Contest 211(A~E)

传送门

A - Blood Pressure

水题

B - Cycle Hit

水题

C - chokudai

题意:给你一个字符串\(S\),问你有多少子序列能构成\(chokudai\),答案\(\mod 1e9+7\).

题解:根据每个连续性,当遍历到某个字符时,状态一定只从它在模板串的上一个字符转移过来,设\(t=chokudai\),某个字符在\(t\)的位置是\(x\),写出状态转移方程:\(dp[x]=(dp[x]+dp[x-1])\mod 1e9+7\).

代码:

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

char s[N];

int main() {
    scanf("%s",s);
    int len=strlen(s);
    ll ans=0;
    unordered_map<char,ll> cnt;
    ll c=0;
    for(int i=0;i<len;++i){
        if(s[i]=='c') c++;
        if(s[i]=='h') cnt['h']=(cnt['h']+c)%mod;
        if(s[i]=='o') cnt['o']=(cnt['o']+cnt['h'])%mod;
        if(s[i]=='k') cnt['k']=(cnt['k']+cnt['o'])%mod;
        if(s[i]=='u') cnt['u']=(cnt['u']+cnt['k'])%mod;
        if(s[i]=='d') cnt['d']=(cnt['d']+cnt['u'])%mod;
        if(s[i]=='a') cnt['a']=(cnt['a']+cnt['d'])%mod;
        if(s[i]=='i') cnt['i']=(cnt['i']+cnt['a'])%mod;
    }
    printf("%lld\n",cnt['i']);
    return 0;
}

D - Number of Shortest paths

题意:一张\(n\)个点,\(m\)条边且边权为\(1\)的无向图,求\(1\)\(n\)的最短路径数。

题解:因为边权为\(1\),我们可以直接跑bfs而不用dijkstra,具体思路就是如果某个点没有到达过,就push进队列,然后更新这个点距离,如果到达过,并且当前距离+1等于他之前更新的距离,那么就更新这个点的路径数。

代码

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

int n,m;
vector<int> edge[N];
int dis[N];
int u,v;
ll cnt[N];

void bfs(){
    for(int i=1;i<=n;++i) dis[i]=-1;
    queue<int> q;
    q.push(1);
    dis[1]=0;
    cnt[1]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(auto to:edge[u]){
            if(dis[to]==-1){
                q.push(to);
                dis[to]=dis[u]+1;
                cnt[to]=cnt[u];
            }
            else if(dis[to]==dis[u]+1){
                cnt[to]=(cnt[to]+cnt[u])%mod;
            }
        }
    }
}

int main() {
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;++i){
        scanf("%d %d",&u,&v);
        edge[u].pb(v),edge[v].pb(u);
    }
    bfs();
    printf("%lld",cnt[n]);
    return 0;
}

E - Red Polyomino

题意:一张\(n\)x\(n\)的#.图,让你在.的位置填上大小为\(k\)的连通块,问右多少种填法。

题解:数据范围很小,就嗯dfs,具体看代码不难理解。

代码:

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

int n,k;
char s[10][10];
int dx[4]={0,0,1,-1},dy[4]={-1,1,0,0};
ll ans;

void dfs(int cnt){
    if(cnt==0){
        ans++;
        return;
    }
    vector<PII> vis;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            if(s[i][j]=='.'){
                bool flag=false;
                for(int t=0;t<4;++t){
                    int tx=i+dx[t],ty=j+dy[t];
                    if(tx>=1 && tx<=n && ty>=1 && ty<=n && s[tx][ty]=='@'){
                        flag=true;
                    }
                }
                if(flag){
                    s[i][j]='@';
                    dfs(cnt-1);
                    s[i][j]='#';
                    vis.pb({i,j});
                }
            }
        }
    }
    for(auto it:vis){
        s[it.fi][it.se]='.';
    }
}

int main() {
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;++i){
        getchar();
        for(int j=1;j<=n;++j){
            scanf("%c",&s[i][j]);
        }
    }
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            if(s[i][j]=='.'){
                s[i][j]='@';
                dfs(k-1);
                s[i][j]='#';
            }
        }
    }
    printf("%lld\n",ans);
    return 0;
}

posted @ 2021-09-07 22:15  Rayotaku  阅读(85)  评论(0编辑  收藏  举报