Codeforces Round 955 (Div. 2, with prizes from NEAR!)
A. Soccer
题意:给定开始前两个分数和结束时两个分数,问有没有可能在这段期间两个队伍从来没有过分数相等的情况。(每次得分只能+1)
思路:确定了两种一定有分数相等的情况(一对之前的分数较低,但是后面的分数较高),其他就是可能没有出现分数相等的情况。
void solve() {
int a, b, c, d;
cin >> a >> b >> c >> d;
if ((a < b && c >= d) || (a > b && c <= d)){
cout << "NO\n";
}
else{
cout << "YES\n";
}
}
B. Collatz Conjecture
题意:给定x,y和k,每次操作必须先增加x,然后判断y是否是x的除数,是的话就一直除,k轮操作后x是多少。
思路:y最小为2,假设x是y的幂,那么运算次数不会超过log(x)次。
每次操作,求出y要成为x的因子,x需要增加多少。其次在运算过程中,如果出现了x为1的情况,那么此时的最后x结果就是1 + (k % (y - 1))。
总结:如果x=1了,那么接下来肯定只考虑k就行。关键是如何考虑?x肯定是先加到y,然后除以y = 1,在这个过程中,每被y整除1次,x就获得1的buff,此时获得的buff应该是k / x,但是k / x 可能是>y的呢? 那么还要继续进行这个操作,有点套娃的感觉,赛时卡在这里了。 其实只要对让k对y - 1取模就行了。这样在数学逻辑上等价于除以y后再判定剩下的数是否能继续被y整除了。而且被y取模有个好处是保证取模后的值<y,那么再加上x的数值1,就是最后答案了,也不需要再考虑这个答案是否会>= y。
这个应该还是数论中的一小点点思维题,奈何数学实在是太差,哎,需要好好学习一下数学了。
其实在x=1时还有种理解方法,此时x + (y - 1)就是y的整数倍了,然后/y又得到了1,所以当x=1时,我们就直接让k%(y - 1),就ok了!这个就得到了后面的操作次数。 然后再加上余数就行了。
void solve() {
long long x, y, k;
cin >> x >> y >> k;
while (k > 0){
long long need = min(k, y - x % y);
if (k >= need){
x += need;
k -= need;
}
else{
x += k;
k = 0;
break;
}
while (x % y == 0){
x /= y;
}
if (x == 1){
break;
}
}
if (k){
x = k % (y - 1) + 1;
}
cout << x << '\n';
}
C. Boring Day
题意:给定n个数(栈结构)和一个区间l,r。不断的从栈顶取出元素,如果连续取出的一些元素的和在l,r区间内,那么记数+1。
问最大计数是多少?每个元素只能参与一次计数,不能重复使用。
思路:维护一个双端队列,然后直接一次遍历即可。
void solve() {
int n, l, r;
cin >> n >> l >> r;
vector<int> a(n);
for (int i = 0; i < n; ++i){
cin >> a[i];
}
deque<int> dq;
int ans = 0;
long long sum = 0;
for (int i = 0; i < n; ++i){
dq.push_back(a[i]);
sum += a[i];
if (sum >= l && sum <= r){
ans ++;
dq.clear();
sum = 0;
}
else{
while(!dq.empty() && sum > r){
sum -= dq.front();
dq.pop_front();
}
if (l <= sum && sum <= r){
ans ++;
dq.clear();
sum = 0;
}
}
}
cout << ans << '\n';
}
D. Beauty of the mountains
题意:给定nm的矩阵,矩阵中有两种东西用0和1表示,每个位置上有一个数值,然后给定一个kk的窗口,每次操作可以在这个窗口内对所有的数值±一个常数c(可以<0)。不限操作次数,问最后能否让矩阵种,0和1两种东西的总和相等。
思路:统计出0的sum和1的sum的差值diff,然后二维前缀和统计出每个位置0和1的数量,然后考虑每个k*k的窗口中0和1分别出现的次数,这个出现的次数代表了我可以纠正其中一方的sum的比例关系。求出所有窗口的出现元素次数后,我们考虑这些元素出现次数的线性组合,能否整除diff,如果能整除diff,那么有解,否则无解。
总结:赛时卡在了最后的线性组合上面,没有想到这个就是简单的贝组定理(拓展欧几里得),今天早上睡醒就知道应该考虑所有元素的gcd。所以还是输在数学太烂上面了。于是放弃玩游戏的时间,整理一下公约数这个东西。
辗转相除法的原理:假设g整除a和b,g是最大公约数,那么b % g一定等于0,a%g也一定等于0。那么(a - b)%g==0也一定成立。基于这个思想,我们不断的考虑(a % b)与b的关系,直到a % b == 0,此时的b就是gcd。
拓展欧几里得(贝组定理),就是D题的线性组合问题。如果在辗转相除的给过程中,不断的维护一个有a和b的表达式来表示余数r,那么最后当r=gcd的时候,这个表达式就是一个线性组合,可以让x * a + y * b = gcd。
简单描述一下这个过程,初始时1 * a + 0 * b = a, 0 * a + 1 * b = b,令x = y = 1, x1 = y1 = 0.
q = a / b
r = a - q * b = (x * a) + (y * b) - (x1 * a) - (y1 * b) =>a * (x - x1) + b * (y - y1)...,
然后a要=b,b要=r了,就令x = x1, y = y1, x1, y1=上面计算出来表示r的系数。
void solve() {
int n, m, k;
cin >> n >> m >> k;
vector<vector<int>> grid(n + 1, vector<int> (m + 1));
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
cin >> grid[i][j];
}
}
vector<vector<char>> moun(n + 1, vector<char>(m + 1));
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
cin >> moun[i][j];
}
}
long long a = 0;
long long b = 0;
vector<vector<int>> pref(n + 1, vector<int>(m + 1, 0));
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
pref[i][j] = (moun[i][j] == '0' ? -1 : 1);
pref[i][j] += pref[i - 1][j];
pref[i][j] += pref[i][j - 1];
pref[i][j] -= pref[i - 1][j - 1];
if (moun[i][j] == '0'){
a += grid[i][j];
}
else{
b += grid[i][j];
}
}
}
long long diff = (b - a);
if (diff == 0){
cout << "YES\n";
return;
}
set<int> sett;
for (int i = k; i <= n; ++i){
for (int j = k; j <= m; ++j){
int t = pref[i][j] - pref[i - k][j] - pref[i][j - k];
t += pref[i - k][j - k];
if (t) {
if (diff % t == 0){
cout << "YES\n";
return;
}
sett.insert(abs(t));
}
}
}
int g = 0;
for (const auto& cur : sett){
g = ::gcd(g, cur);
if (diff % g == 0){
cout << "YES\n";
return;
}
}
cout << "NO\n";
}
世界不会因为你的停歇而停止进步,但会因为你的参与而更加精彩(? 疯狂掉分,实在是感觉不到精彩在哪。。可能就是为了让别人更精彩:C)
有模板写题就是好用,只要维护固定的几个函数即可。
模板放在了下面的仓库,如果使用,请点进去点个star。
https://github.com/yxc-s/programming-template/tree/master
该仓库是一个新仓库,旨在打造一个通用的C++算法编程竞赛模板,包含数据结构,数论等各种实用的算法编程模板。如果您使用的语言不是C++,也可以将对应的代码实现翻译成其他语言来使用。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】