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;
}
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮