第一题
Acwing.4725 末尾字母
难度:easy
给定一个由大小写字母、空格和问号组成的字符串。
请你判断字符串中的最后一个字母是否是元音字母。
我们认为元音字母共有 6 个,分别为:A、E、I、O、U、Y(当然还有它们的小写)。
输入格式
一个由大小写字母、空格和问号组成的字符串。
保证问号在字符串中恰好出现一次,且一定出现在最后。
字符串中至少包含一个字母。
输出格式
如果字符串中的最后一个字母是元音字母,则输出 YES,否则输出 NO。
注意,我们问的是最后一个字母,而不是最后一个字符,空格和问号不算作字母。
数据范围
所有测试点满足,输入字符串的长度范围 [2,100]。
输入样例1:
Is it a melon?
输出样例1:
NO
输入样例2:
Is it an apple?
输出样例2:
YES
输入样例3:
Is it a banana ?
输出样例3:
YES
输入样例4:
Is it an apple and a banana simultaneouSLY?
输出样例4:
YES
代码:
#include<iostream>
#include<unordered_set>
using namespace std;
int main(){
//先用一个哈希表来记录所有的元音字母
unordered_set<char> uset;
string vowel = "AEIOUYaeiouy";
for(auto &c:vowel) uset.insert(c);
//这里用getline来处理输入 cin遇到空格就会停止读取
string s;
getline(cin,s);
//从倒数第二个字符开始遍历,遇到字母就退出
int n = s.size();
int i = n - 2;
for(;i >= 0;i--){
if(isalpha(s[i])) break;
}
//此时的s[i]就是最后一个字母,判断它是否为元音字母 输出结果
if(uset.count(s[i])) puts("YES");
else puts("NO");
return 0;
}
时间复杂度:O(N)
第二题
Acwing.4276 寻找数字
难度:mid
给定一个正整数 n,请你找到一个正整数 x,要求:
- x≥n
- x 的各个数位均不包含 4 和 7 以外的数字,且 x 中包含的 4 的数量与 7 的数量恰好相等。
- 满足前两个条件的前提下,x 应尽可能小。
输入格式
一个正整数 n。
输出格式
一个正整数,表示 x。
数据范围
前 6 个测试点满足 1≤n≤5000。
所有测试点满足 1≤n≤ 1 0 9 10^9 109。
输入样例1:
4500
输出样例1:
4747
输入样例2:
47
输出样例2:
47
分析:
代码
#include<iostream>
#include<set>
using namespace std;
using LL = long long;
int n;
set<LL> s;
//注意:x的值是会超过int的最大值的,所以这里需要用 long long 来接收
void dfs(int u,LL x,int cnt){
if(u > 10) return;
//cnt 是4的个数 2 * cnt = u 说明7的个数和cnt相同 满足条件
if(cnt * 2 == u) s.insert(x);
//cnt 只记录x 中 4的个数
dfs(u + 1,x * 10 + 4,cnt+1);
dfs(u + 1,x * 10 + 7,cnt);
}
int main(){
cin>>n;
dfs(0,0,0);
LL ans = -1;
//找出第一个大于n的数,即答案
for(auto &x:s){
if(x >= n){
ans = x;
break;
}
}
cout<<ans<<endl;
return 0;
}
时间复杂度:O( 2 m 2^m 2m)
第三题
Acwing.4727 摆放棋子
难度:hard
给定 n1 个完全相同的黑色棋子和 n2 个完全相同的白色棋子。
请你将所有棋子摆成一排。
在所有棋子都摆放好后,需满足:
不得有超过 k1 (即大于 k1)个黑色棋子连续相邻的排在一起。
不得有超过 k2 (即大于 k2)个白色棋子连续相邻的排在一起。
请问一共有多少种不同的摆放方法。
由于结果可能很大,你只需要输出对 1 0 8 10^8 108 取模后的结果。
输入格式
共一行,包含 4 个整数 n1,n2,k1,k2。
输出格式
输出满足要求的摆放方法数量对 1 0 8 10^8 108 取模后的结果。
数据范围
前 4 个测试点满足 1≤n1,n2≤10。
所有测试点满足 1≤n1,n2≤100,1≤k1,k2≤10。
输入样例1:
2 1 1 10
输出样例1:
1
输入样例2:
2 3 1 2
输出样例2:
5
输入样例3:
2 4 1 1
输出样例3:
0
分析:
dp代码
#include<iostream>
#include<algorithm>
using namespace std;
using LL =long long;
const int N = 105,M = 15,MOD = 1e8;
int f[N][N][M][M];
int n1,n2,k1,k2;
int main(){
cin>>n1>>n2>>k1>>k2;
f[0][0][0][0] = 1;
for(int i = 0;i <= n1;i++){
for(int j = 0;j <= n2;j++){
for(int k = 0;k <= k1;k++){
for(int u = 0;u <= k2;u++){
int v = f[i][j][k][u];
if(i+1<=n1&&k+1<=k1)f[i+1][j][k+1][0] = (f[i+1][j][k+1][0]+v)%MOD;
if(j+1<=n2&&u+1<=k2)f[i][j+1][0][u+1] = (f[i][j+1][0][u+1]+v)%MOD;
}
}
}
}
LL ans = 0;
for(int i = 0;i <= k1;i++) ans = (ans + f[n1][n2][i][0])%MOD;
for(int i = 0;i <= k2;i++) ans = (ans + f[n1][n2][0][i])%MOD;
cout<<ans<<endl;
return 0;
}
时间复杂度为 O( N 2 N^2 N2 * K 2 K^2 K2)
记忆化搜索代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
using LL = long long;
const int MOD = 1e8,N = 105,M = 15;
int f[N][N][M][M];
int n1,n2,k1,k2;
int dfs(int u,int v,int w,int z){
if(!u && !v) return 1;
if(f[u][v][w][z] != -1) return f[u][v][w][z];
LL sum = 0;
if(u && w + 1 <= k1) sum = (sum + dfs(u-1,v,w+1,0))%MOD;
if(v && z + 1 <= k2) sum = (sum + dfs(u,v-1,0,z+1))%MOD;
f[u][v][w][z] = sum;
return sum;
}
int main(){
cin>>n1>>n2>>k1>>k2;
memset(f,-1,sizeof f);
cout<<dfs(n1,n2,0,0)<<endl;
return 0;
}
时间复杂度为 O( N 2 N^2 N2 * K 2 K^2 K2)