C - chokudai
题意:
给你一个字符串(长度<1e5),问有几个子序列是 ”chokudai" ,答案取余1e9+7
输入
chchokudai
输出
3
分析:
简单DP,除了第一个字母,其他字母都是上一个字母出现数量与该字母数量的和,代码很好理解
#include<iostream>
using namespace std;
const int mod=1e9+7;
int ans[8];
int main()
{
string s;
cin >> s;
for(int i=0;i<s.size();i++)
{
if(s[i]=='c') ans[0]++;
else if(s[i]=='h') ans[1]=(ans[1]+ans[0])%mod;
else if(s[i]=='o') ans[2]=(ans[2]+ans[1])%mod;
else if(s[i]=='k') ans[3]=(ans[3]+ans[2])%mod;
else if(s[i]=='u') ans[4]=(ans[4]+ans[3])%mod;
else if(s[i]=='d') ans[5]=(ans[5]+ans[4])%mod;
else if(s[i]=='a') ans[6]=(ans[6]+ans[5])%mod;
else if(s[i]=='i') ans[7]=(ans[7]+ans[6])%mod;
}
cout<<ans[7]<<endl;
return 0;
}
D - Number of Shortest paths
题意:
一幅图,有n个点m条双向边(n=[2,2e5],m=[0,2e5]),边长都是1,问第一个点到第n个点的最短路线的数量是多少,答案取模1e9+7
输入
4 5 (n个点,m条边,接下来m行)
2 4
1 2
2 3
1 3
3 4
输出
2
注:1->2->4 and 1->3->4
分析:
用bfs搜最短路
#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
const int N=8e5+10;
const int M=1e9+7;
int h[N],ne[N],e[N],idx;
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
int n,m;
int dist[N],ans[N];//ans表示1到当前下标点的最短路径的方案数
bool st[N];
queue<int> q;
void bfs(int x)
{
q.push(x);
dist[x]=0;
st[x]=true;
ans[x]=1;//初始化
while(q.size())
{
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(!st[j])
{
dist[j]=dist[t]+1;
ans[j]=ans[t];//如果没有遍历过j点,那么1~j的方案数==1~t的方案数
q.push(j);
st[j]=true;
}
else//若已经遍历过且距离==当前根节点的距离+1,那么1~j的方案数=1~j的方案数=+1~t的方案数
{
if(st[j]&&dist[j]==dist[t]+1)
{
ans[j]=(ans[j]+ans[t])%M;
}
}
}
}
}
int main()
{
memset(h,-1,sizeof(h));
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
bfs(1);
cout<<ans[n]<<endl;
}
E - Red Polyomino
题意:
给你一个n*n的矩阵(n=[1,8])和一整数k,矩阵中的元素值为 **#**的点是不可选择的点,问:有多少个大小为k的连通块(这里大小指元素数)
输入
3 (n)
5(k)(接下来是n*n的矩阵)
#.#
…
…#
输出
5
注释:从6个点种选择 5 (k) 个点,方案有6种,但是只有5种是连通的,所以输出5
分析:
一开始我的想法是从所有可以选择的点中选k个,用dfs搜到所有方案,再对每一个方案判断是否连通块,TLE了
后来换了一下思路,如果我能在dfs找方案的时候保证找到的每一个方案是连通块,那么就可以减少很多时间复杂度,代码如下
#include<iostream>
#include<unordered_map>
#include<queue>
#include<string.h>
using namespace std;
const int N=9;
unordered_map<string,int> mp;//因为在搜索过程很容易搜到重复情况,所以用哈希表存一下
int dx[]={1,-1,0,0},dy[]={0,0,1,-1};//下上右左
char a[N][N];
bool st[N][N];
long long n,k,ans;
string jihe()//将二维矩阵压缩成一维的字符串
{
string an;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
an+=a[i][j];
return an;
}
void dfs(int s)
{
string tmp=jihe();
if(mp[tmp]>=1) return ;//如果存过直接return
mp[tmp]=1;
if(s==0)
{
ans++;
return ;
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(a[i][j]!='.') continue;
for(int k=0;k<4;k++)
{
int x=i+dx[k],y=j+dy[k];
if(x>=0&&y>=0&&x<n&&y<n&&a[x][y]=='@')//这句的意义是a[i][j]是. 且他附近至少有一个@才会将a[i][j]变成@
{
a[i][j]='@';
dfs(s-1);
a[i][j]='.';
}
}
}
}
}
int main()
{
cin>>n>>k;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(a[i][j]=='.')
{
a[i][j]='@';
dfs(k-1);
a[i][j]='.';
}
}
}
cout<<ans<<endl;
}