24暑期第七次训练C组
A
生活大爆炸版石头剪刀布
纯模拟,保证AB之间能对应就行。
给出较朴素做法。
bool caiquan(int,int);
int main(void)
{
int n,x,y,ans1 = 0,ans2 = 0,stp;
cin >> n >> x >> y;
vector<int> a(x);
vector<int> b(y);
for(auto &i : a) cin >> i;
for(auto &i : b) cin >> i;
for(int i=0,j=0,t=0;t < n;t++)
{
ans1 += caiquan(a[i],b[j]);
ans2 += caiquan(b[j],a[i]);
++i,++j;
if(i == x) i = 0;
if(j == y) j = 0;
}
cout << ans1 << ' ' << ans2 << '\n';
}
bool caiquan(int a,int b)
{
bool ans = false;
if(a == 0)
{
if(b == 2 || b == 3) ans = true;
}
else if(a == 1)
{
if(b == 0 || b == 3) ans = true;
}
else if(a == 2)
{
if(b == 1 || b == 4) ans = true;
}
else if(a == 3)
{
if(b == 2 || b == 4) ans = true;
}
else
{
if(b == 0 || b == 1) ans = true;
}
return ans;
}
B
笨小猴
模拟,可以开map模拟,但是只出现字符,开数字模拟也可,甚至更快。
void func()
{
string st;
cin >> st;
map<char,int> cnt;
for(auto &i : st) cnt[i]++;
int mx = 0, mn = 0x3f3f;
for(auto &i : cnt)
{
mx = max(mx,i.second);
mn = min(mn,i.second);
}
if(slove(mx - mn)) cout << "Lucky Word\n" << mx - mn << '\n';
else cout << "No Answer\n0";
}
bool slove(int z)// 判素数
{
if(z <= 1) return false;
for(int i=2;i<=z/i;++i)
{
if(z % i == 0) return false;
}
return true;
}
C
过河卒
超纲题,二维dp。
根据题意,卒只能王下或者往右移动,所以 [i,j] 状态由[i−1,j]和[i,j−1]转移。
设dp[i][j]为移动到(i,j)的次数,那么可得转移方程:
dp[i][j]=dp[i−1][j]+dp[i][j−1]
但是因为马的存在,有部分点不可移动,这时只需要单独处理,到此处时dp[i][j]=0即可。
因为想着最后一组题,特意出了点超纲的考算法的题目。其实可能也不超纲,你们专业课好像学了动态规划。
void func()
{
int n,m,a,b;
cin >> n >> m >> a >> b;
int dp[N][N];
int vis[N][N];
n += 2,m += 2,a += 2,b += 2;// 保证边界往外一格存在,防RE
memset(vis,0,sizeof vis);
memset(dp,0,sizeof dp);
int dx[] = {1,2,2,1,-1,-2,-2,-1};
int dy[] = {2,1,-1,-2,-2,-1,1,2};// 表示马的移动
dp[1][2] = 1;
vis[a][b] = 1;
for(int i=0;i<8;++i) vis[a+dx[i]][b+dy[i]] = 1;// 计算马禁止的坐标
for(int i=2;i<=n;++i)
{
for(int j=2;j<=m;++j)
{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
if(vis[i][j] == 1) dp[i][j] = 0;
}
}
cout << dp[n][m] << '\n';
}
D
Contest Proposal
因为数据很小,可以写暴力一点。
每次比较ai,bi,ai不符合条件删去,然后把bi放入,再给a排序。这样就能保证顺序了。这时复杂度O(n2logn)。
void func()
{
int n,ans = 0;
cin >> n;
vector<int> a(n),b(n);
for(auto &i : a) cin >> i;
for(auto &i : b) cin >> i;
for(int i=0;i<n;++i)
{
if(b[i] < a[i])
{
a.pop_back();
a.push_back(b[i]);
sort(a.begin(),a.end());
ans ++;
}
}
cout << ans << '\n';
}
实际可以用更短的代码写出O(n)的解法。
因为在ai>bi后插入了新数字,这个数字大小一定在ai−1和ai之间,所以和bi+1比较的还是ai。具体如下。
void func()
{
int n,ans = 0;
cin >> n;
vector<int> a(n),b(n);
for(auto &i : a) cin >> i;
for(auto &i : b) cin >> i;
for(int i=0,j=0;j<n;++j)
{
if(a[i] <= b[j]) ++i;
else ans++;
}
cout << ans << '\n';
}
E
Coin Games
每个人操作实际只有以下三种情况。
分别使实际可操作次数+2,−2,不变。在边界操作不翻转,可理解成第三种情况。每次操作都使得可操作次数−1后偶数次变化,都不影响结果。因为答案就是可操作次数的奇偶性。
void func()
{
int n;
string st;
cin >> n >> st;
int cnt = 0;
for(int i=0;i<n;++i)
if(st[i] == 'U') cnt++;
if(cnt % 2) cout << "YES\n";
else cout << "NO\n";
}
F
Phone Desktop
每个屏幕3×5,可放2个2×2,其余可填7个1×1先算2×2需要多少个屏幕,再算当前屏幕是否可放下所有1×1,根据1×1的量加屏幕。
void func()
{
int a,b;
cin >> a >> b;
int ans = (b+1) / 2;
int stp = a - (ans*15 - 4*b);
if(stp > 0) ans += (stp + 14) / 15;
//当前屏幕是否可以放下所有a,不能则再加屏幕.
cout << ans << '\n';
}
G
Chess For Three
因为每次对弈都使总分+2,所以总分不是偶数则不可能。
又因为求最大可能和棋次数。那么先考虑全和棋的情况。
全和棋和棋数为得分/2,因为c得分最高,所以参与了最多次的对弈。
考虑极限情况,所有对弈都有c参与。可得:
- 在a+b=c 时,a,b可以全向c和棋。答案即为总分/2。
进而可推得:
- 在a+b<c 时,全和棋不满足答案,a,b全向c和棋,c再赢若干次。和棋次最多。答案即(a+b)/2
- 在a+b>c 时,全和棋是满足答案的。答案即为总分/2。
void func()
{
int a,b,c;
cin >> a >> b >> c;
int sum = 0;
sum = a + b + c;
if(sum % 2 == 0) cout << (a + b >= c ? sum / 2 : a + b) << '\n';
else cout << -1 << '\n';
}
H
Symmetric Encoding
按题意处理出r串,使得对称映射就行。
void func()
{
int n;
string st,r;
cin >> n >> st;
r = st;
sort(r.begin(),r.end());
r.erase(unique(r.begin(),r.end()),r.end());
int len = r.size();
map<char,char> mp;
for(int i=0;i<len;++i) mp[r[i]] = r[len - 1 - i];
for(int i=0;i<n;++i) st[i] = mp[st[i]];
cout << st << '\n';
}
I
Little Nikita
设放上的操作有x次,拿下的操作有y次,那么可得
- x=y=n
- x−y=m
那么n+m=2×x,n+m为偶数。
void func()
{
int n,m;
cin >> n >> m;
if((n + m) % 2 == 0 && n >= m) cout << "YES\n";
else cout << "NO\n";
}
J
Update Queries
题意说明:可以将s按ind数组的索引替换为b中对应字符。对ind和b排序,使得结果字符串的字典序最小。
因为并不需要输出排列后的ind和b,所以只需要输出最小字典序的答案即可,二者排序并不重要。
只需要将ind代表的可替换位置,从前到后替换为b中从小到大的字符。
void func()
{
int n,m;
cin >> n >> m;
string s,c;
cin >> s;
set<int> ind;
while(m--)
{
int stp;cin >> stp;
ind.insert(stp);
}
cin >> c;
sort(c.begin(),c.end());
int j=0;
for(auto &i : ind) s[i-1] = c[j++];
cout << s << '\n';
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [翻译] 为什么 Tracebit 用 C# 开发
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端