Codeforces Round 952 (Div. 4)
A
读入两个字符串,交换第一位即可。
B
题意
给定整数
-
。 -
最大,其中 为满足 最大的正整数。
思路
赛时思路
可以直接枚举
由于是像筛法那样的暴跳,总复杂度为
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;
const int N = 1e6 + 100;
int t , n;
signed main() {
cin >> t;
while(t --) {
cin >> n;
int maxx = 0 , ans = n;
for(int j = 2;j <= n;j ++) {
int sum = 0;
for(int k = 1;k * j <= n;k ++)
sum += k * j;
if(sum > maxx) {
ans = j;
maxx = sum;
}
}
cout << ans << "\n";
}
return 0;
}
另解
我们注意到当
证明:
根据等差数列求和公式我们得到:
根据以上式子放缩:
当
当
上式比下式:
我们只需要证明这个式子
若
若
若
若
证毕。
如果有简单证明请速速告诉我,我被这证明折磨麻了!
C
题意
一个序列中若存在一个数等于序列中其他所有数的和,则该序列为好序列。
问有多少个
思路
如果存在一个数等于其他数的和,那么这个数必然是序列中最大的。
设最大的数为
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;
const int N = 1e6 + 100;
int t , n , a[N];
signed main() {
cin >> t;
while(t --) {
cin >> n;
int maxx = 0 , sum = 0 , ans = 0;
for(int i = 1;i <= n;i ++) {
cin >> a[i];
sum += a[i];
maxx = max(maxx , a[i]);
if(maxx * 2 == sum) ans ++;
}
cout << ans << "\n";
}
return 0;
}
D
题意
给定一个由 #
和 .
组成的 #
构成的完整的曼哈顿圆,求这个曼哈顿圆的中心。
以 #
,
思路
画图发现曼哈顿圆一定是一个菱形(
那么中心点就是 #
最长的一行的连续 #
的中点。
扫一遍得到横坐标 #
纵坐标 #
纵坐标
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;
const int N = 1e6 + 100;
char ch[N];
int t , n , m , a[N];
signed main() {
cin >> t;
while(t --) {
cin >> n >> m;
int maxx = 0;
int x , y;
for(int i = 1;i <= n;i ++) {
scanf("%s" , ch + 1);
int now = 0 , zh = 0 , zq = 0;
for(int j = 1;j <= m;j ++) {
if(ch[j] == '#') {
if(now == 0) zq = j;
now ++ , zh = j;
}
}
if(now > maxx) {
maxx = now;
x = i;
y = (zq + zh) / 2;
}
}
cout << x << ' ' << y << "\n";
}
return 0;
}
E
思路
可以枚举长和宽
根据乘法原理可得,放置方案数为
复杂度
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;
const int N = 1e6 + 100;
char ch[N];
int t , x , y , z , k;
signed main() {
cin >> t;
while(t --) {
cin >> x >> y >> z >> k;
int maxx = 0;
for(int i = 1;i <= x;i ++) {
for(int j = 1;j <= y;j ++) {
if(k % i == 0) {
int now = k / i;
if(now % j == 0) {
int dsw = now / j;
maxx = max(maxx , (x - i + 1) * (y - j + 1) * max(0ll , (z - dsw + 1)));
}
}
}
}
cout << maxx << "\n";
}
return 0;
}
F
小时候看这集 fst 了。
题意
有个 boss 有
每一回合你可以使用所有已冷却的技能,然后该技能会进入冷却并在
求最少多少回合击败 boss。
思路
对 boss 造成的伤害是随着回合数单调不降的。
所以直接二分答案就行了。
若进行了
注意:计算总伤害会爆 long long。所以在计算过程中若足够击败 boss 就应直接退出循环。笔者就是因为这个 fst 了。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;
const int N = 1e6 + 100;
char ch[N];
int t , n , m , z , k , a[N] , b[N];
signed main() {
cin >> t;
while(t --) {
cin >> n >> m;
for(int i = 1;i <= m;i ++)
cin >> a[i];
for(int i = 1;i <= m;i ++)
cin >> b[i];
int l = 1 , r = 1e12;
int ans = 1;
while(l <= r) {
int mid = l + r >> 1;
int sum = 0;
for(int i = 1;i <= m;i ++) {
int cs = (mid - 1) / b[i] + 1;
sum += cs * a[i];
if(sum >= n) break;
}
if(sum >= n) {
ans = mid;
r = mid - 1;
} else l = mid + 1;
}
cout << ans << "\n";
}
return 0;
}
G
题意
设
给定
-
。 -
。
思路
首先满足该条件的一个充分条件是
所以我们猜测这个也是它的必要条件,考虑证明。
对于单独的一位
则
后者小于前者,证明:
把
所以必要条件成立。
计算答案
这题计算答案也没那么简单,根据最高位不能填
对于
所以对于
根据等比数列求和公式可得到上式等于
这个式子用快速幂和逆元相关知识就能求出来了。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;
const int N = 1e6 + 100;
const int mod = 1e9 + 7;
char ch[N];
int t , n , m , z , k , a[N] , b[N];
int ksm(int x,int y) {
int res = 1;
for(;y;y >>= 1 , x = x * x % mod)
if(y & 1)
res = res * x % mod;
return res;
}
signed main() {
cin >> t;
while(t --) {
cin >> n >> m >> k;
int wd = (9 / k);
int now = (((ksm(wd + 1 , m - n) - 1) % mod) + mod) % mod;
now = ksm(wd + 1 , n) % mod * now % mod;
cout << now << "\n";
}
return 0;
}
H1
题意
给定一个由 #
和 .
组成的 #
构成的连通块最大。
操作:选定一行或一列,将其全部变为 #
。
输出操作后最大连通块点数。
思路
很自然地想到枚举每一行/每一列,难点在于怎么计算答案。
我们先考虑填行的情况。
如果我们把一行填满,则相当于桥一样把这条线两边的连通块连起来了。
所以当我们枚举第 .
的数量,并将第
这里选择先
然后计算答案的时候,用
填列的做法和填行没有任何区别。
代码
代码复杂程度远难于思路的一题。
H2
题意
给定一个由 #
和 .
组成的 #
构成的连通块最大。
操作:选定一行和一列,将其全部变为 #
。
输出操作后最大连通块点数。
思路
如果使用 Easy Version 的思路,复杂度是
由于选一行一列会有交集的连通块,所以无法单独考虑行或列再计算答案。
因此还是考虑枚举行和列,到这复杂度为
既然暴力计算答案不行,那么我们就想想能不能预处理出答案。
对于一个连通块,向上延伸到
这个贡献,我们用差分数组记录,比如行差分数组
列差分数组也是同理。
做到这里会发现枚举行列的话,会有连通块被重复计算了一次。那么考虑怎么减掉这个贡献。
再整一个二维数组
时间复杂度
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧