A - Not Found
翻译:
给您一个字符串S,长度在1 到25 之间,由小写英文字母组成。
输出S 中没有出现的一个小写英文字母。
如果有多个这样的字母,可以输出其中任何一个。
思路:
数组记录存在于 s 中的字母。(模拟)
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MX = 2e5+10;
void solve(){
string s;
cin>>s;
vector<int> num(26,0);
for (char c:s) num[c-'a'] = 1;
for (int i=0;i<26;i++){
if (num[i]==0){
cout<<(char)(i+'a')<<endl;
return;
}
}
}
int main(){
// 关闭输入输出流同步
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 不使用科学计数法
// cout<<fixed;
// 四舍五入中间填保留几位小数,不填默认
// cout.precision();
solve();
return 0;
}
B - Grid Rotation
翻译:
有两个网格 S 和 T,每个网格有 N 行 N 列。让(i,j) 表示从上到下第 i 行和从左到右第 j 列的单元格。
网格 S 和 T 的每个单元格都被涂成白色或黑色。如果
为 .,则 S 的单元格 (i,j) 为白色;如果
为 #,则 S 的单元格 (i,j) 为黑色。这同样适用于 T。
您可以按任意顺序执行以下两种类型的操作任意多次。找出使网格 S 与网格 T 相同所需的最少操作次数。
- 选择网格 S 中的一个单元格并改变其颜色。
- 将整个网格 S 顺时针旋转 90 度。
思路:
模拟一下得到:对于点(i,j),
- 顺时针旋转90度,对应点(j,n-i+1);
- 顺时针旋转180度,对应点(n-i+1,n-j+1);
- 顺时针旋转270度,对应点(n-j+1,i);
可以想到旋转最多发生一次,得到转后的答案进行比较即可。(模拟)
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MX = 2e5+10;
void solve(){
int n;
cin>>n;
vector<vector<char>> a(n+1,vector<char>(n+1)),b(n+1,vector<char>(n+1));
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
cin>>a[i][j];
}
}
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++) cin>>b[i][j];
}
vector<int> res(4,0);
for (int i=0;i<4;i++) res[i] = i;
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
res[0] += (b[i][j]!=a[i][j]);
res[1] += (b[j][n-i+1]!=a[i][j]);
res[2] += (b[n-i+1][n-j+1]!=a[i][j]);
res[3] += (b[n-j+1][i]!=a[i][j]);
}
}
int ans = res[0];
for (int i=0;i<4;i++){
// cout<<res[i]<<endl;
ans = min(ans,res[i]);
}
cout<<ans<<endl;
}
int main(){
// 关闭输入输出流同步
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 不使用科学计数法
// cout<<fixed;
// 四舍五入中间填保留几位小数,不填默认
// cout.precision();
solve();
return 0;
}
C - Cycle Graph?
翻译:
给你一个简单的无向图,它有 N 个顶点和M 条边。顶点编号为 1,2,...,N,边编号为 1,2,...,M。边 i 连接顶点 A i 和 B i。
请判断该图是否为循环图。
思路:
先判断是否N==M。不是的话,存在多余边。
深度搜索,判断是否能回到原点并经过了N个点。(dfs)
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MX = 2e5+10;
int n,m;
void solve(){
cin>>n>>m;
vector<vector<int>> graph(n+1);
for (int v,u,i=1;i<=m;i++){
cin>>u>>v;
graph[u].push_back(v);
graph[v].push_back(u);
}
if (n!=m){
cout<<"No"<<endl;
return;
}
vector<int> vis(n+1,0);
auto dfs = [&](auto&& dfs ,int i,int fa,int cnt)->void{
vis[i] = 1;
for (int j:graph[i]){
if (j!=fa){
if (vis[j]){
if (cnt!=n)
cout<<"No"<<endl;
else cout<<"Yes"<<endl;
exit(0);
}
vis[j] = 1;
dfs(dfs,j,i,cnt+1);
}
}
};
dfs(dfs,1,-1,1);
cout<<"No"<<endl;
}
int main(){
// 关闭输入输出流同步
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 不使用科学计数法
// cout<<fixed;
// 四舍五入中间填保留几位小数,不填默认
// cout.precision();
solve();
return 0;
}
D - Goin' to the Zoo
翻译:
在 AtCoder 国家有 N 个动物园,编号从 1 到 N。第 i 个动物园的门票是 C i 日元。
铃木先生喜欢 M 种动物,即动物 1,...,M。动物 i 可以在 K i 个动物园看到,即动物园 A i,1,...,A i,K i。
求如果M 种动物每种至少看两次,所需的最低门票总额。
如果您多次游览同一动物园,则认为每次游览都能看到那里的动物。
思路:
一个动物园最多看两次,多了没意义。在此基础上遍历每个动物园的观光次数。最坏O(
)。(暴力)
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MX = 2e5+10;
ll n,m,res = LLONG_MAX;
vector<ll> c;
vector<vector<ll>> zoos;
vector<ll> vis;
void dfs(ll i,ll costs){
if (costs>res) return;
if (i==n+1){
ll f = 1;
vector<ll> tmp(m+1,2);
for (ll j=1;j<=n;j++){
for (ll k:zoos[j]){
tmp[k]-=vis[j];
}
}
for (ll j=1;j<=m;j++) if (tmp[j]>0) f = 0;
if (f) res = min(res,costs);
return;
}
for (ll j=0;j<=2;++j){
vis[i] = j;
dfs(i+1,costs+j*c[i]);
}
}
void solve(){
cin>>n>>m;
c.resize(n+1);
zoos.resize(n+1);
vis.resize(n+1,0);
for (ll i=1;i<=n;i++) cin>>c[i];
for (ll k,zoo,i=1;i<=m;i++){
cin>>k;
for(ll j=1;j<=k;j++){
cin>>zoo;
zoos[zoo].push_back(i);
}
}
dfs(1,0ll);
cout<<res<<endl;
}
int main(){
// 关闭输入输出流同步
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 不使用科学计数法
// cout<<fixed;
// 四舍五入中间填保留几位小数,不填默认
// cout.precision();
solve();
return 0;
}
E - Bowls and Beans
翻译:
一排有 N 个大碗,从左边开始依次编号为0,1,...,N-1。
每个碗 i(1≤i≤N-1)上都写有一个整数 C i,最初装有 A i 粒豆子。
碗 0 上没有写任何整数,最初也没有豆子。
考虑重复下面的操作任意多次:
- 选择一个碗 i(1≤i≤N-1),从中取出一颗或多颗豆子。
- 将取出的豆子在
碗中自由分配。
- 从形式上看,当你取出 k 粒豆子时,你必须把总共k 粒豆子放进碗
中,你可以选择每碗放多少粒豆子。
求将所有豆子放入 0 号碗所需的最少操作数。
思路:
碗中有豆的是一定要操作的。
将豆子分配到碗中有豆子的其他碗是优先考虑的。
memo[i]:在点 i 到有豆的其他碗的最小操作数。(动态规划,贪心)
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MX = 2e5+10;
void solve(){
int n;cin>>n;
vector<int> c(n+1),a(n+1);
a[1] = 1;
for (int i=2;i<=n;i++)cin>>c[i];
for (int i=2;i<=n;i++) cin>>a[i];
vector<int> memo(n+1,INT_MAX);
memo[1] = 1;
for (int i=2;i<=n;i++){
for (int j=i-1;j>=max(1,i-c[i]);j--){
if (a[j]) memo[i] = 1;
else{
memo[i] = min(memo[i],memo[j]+1);
}
}
}
int cnt = 0;
for (int i=n;i>=2;i--){
if (a[i]==0) continue;
cnt+=memo[i];
}
cout<<cnt<<endl;
}
int main(){
// 关闭输入输出流同步
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 不使用科学计数法
// cout<<fixed;
// 四舍五入中间填保留几位小数,不填默认
// cout.precision();
solve();
return 0;
}
G - Specified Range Sums
翻译:
给你一个整数 N 和长度-M 整数序列 L=(L1,L2,...,LM), R=(R1,R2,...,RM), 和 S=(S1,S2,...,SM)。
判断是否存在满足以下条件的长度为 N 的正整数序列 A。如果存在,求 A 的最小可能和。
思路:
C_i为下标1到i的和,那么
,且
。
先利用差分约束的思想,转换为有超级原点求最大路径的图(对于差分路径,最短路求得的是最大解,而最长路求得是最小解)。有负权值的出现使用bellman_ford算法,答案为0到n的最大路径。找不到此路径(存在负环)即不存在A,输出-1。
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
struct Edge{
ll v,w;
};
void solve(){
ll n,m;cin>>n>>m;
vector<vector<Edge>> graph(n+1);
for (ll l,r,s,i=1;i<=m;i++){
cin>>l>>r>>s;
graph[l-1].push_back({r,s});
graph[r].push_back({l-1,-s});
}
for (ll i=0;i<n;i++){
graph[i].push_back({i+1,1});
}
for (ll i=1;i<=n;i++){
graph[0].push_back({i,0});
}
vector<ll> vis(n+1,0),cnt(n+1,0),d(n+1,LLONG_MIN);
queue<ll> q;
d[0] = 0,vis[0]=1,q.push(0);
while (!q.empty()){
ll u = q.front();q.pop(),vis[u] = 0;
for (auto ed:graph[u]){
ll v = ed.v,w = ed.w;
if (d[v]<d[u]+w){
d[v] = d[u]+w;
cnt[v] = cnt[u]+1;
if (cnt[v]>=n+1){
cout<<-1<<endl;
return;
}
if (!vis[v]) vis[v]=1,q.push(v);
}
}
}
cout<<d[n]<<endl;
}
int main(){
// 关闭输入输出流同步
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 不使用科学计数法
// cout<<fixed;
// 四舍五入中间填保留几位小数,不填默认
// cout.precision();
solve();
return 0;
}
有建议可以评论,我会积极改进qwq。