1.小红的数字分裂

- 关键观察
每次分裂操作 x → a + b,数组的总和是不变的 。最终所有元素都等于同一个值 T,因此:
- 最终元素个数为
k,那么sum = k × T - 每个原始元素
a_i必须是T的倍数(因为a_i要被拆成若干个T)
要让操作次数最少,就要让 k 尽可能小(操作次数 = k - n),等价于让 T 尽可能大。
- 核心结论
T 的最大值就是数组所有元素的最大公约数(GCD)。
- 所有
a_i都是GCD的倍数,因此都能被拆成若干个GCD - 设最终元素个数
k = sum / GCD - 最少操作次数 =
k - n
ac代码:
cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
long long gcd(long long a, long long b) {
while (b) {
long long temp = b;
b = a % b;
a = temp;
}
return a;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<long long> a(n);
long long sum = 0;
long long g = 0;
for (int i = 0; i < n; ++i) {
cin >> a[i];
sum += a[i];
g = gcd(g, a[i]);
}
long long k = sum / g;
cout << k - n << endl;
return 0;
}
2.小红的回文子串

错误代码:
cpp
#include<iostream>
#define int long long
using namespace std;
signed main()
{
string s;cin>>s;
int n = s.size();
s = ' ' + s;
if(n<=2)
{
cout<<0;
return 0;
}
int ret = 0,pos = 0,cur = 0,flag = 1;
for(int l=1,r=3;r<=n;r++)
{
//出窗口
if(s[r]!=s[r-2]&&pos)
{
while(l!=flag)
{
cur--;
l++;
}
l++;cur--;//跳到了上一次转换数字的下一个数字
pos = 0;
r--;//重来一遍
continue;
}
cur++;
if(s[r]!=s[r-2])
{
flag = r-2;
pos = 1;
}
ret = max(ret,cur);
}
cout<<ret;
return 0;
}
- 错误原因:例如 axbxa,我的代码会首先将第一个a改为b,所以无法得到正确答案
- 正确解法:枚举每个位置,并在每个位置枚举26个字母
ac代码:
cpp
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string s;
cin >> s;
int n = s.size();
if (n <= 2) {
cout << 0 << endl;
return 0;
}
// 计算原始的长度为3的回文子串数量
int base = 0;
for (int i = 0; i + 2 < n; ++i) {
if (s[i] == s[i + 2]) base++;
}
int max_add = 0;
// 枚举修改每个位置
for (int i = 0; i < n; ++i) {
// 原来的字符
char original = s[i];
// 枚举修改成任意字符
for (char c = 'a'; c <= 'z'; ++c) {
if (c == original) continue; // 不用改
int add = 0;
// 包含i的三元组有:(i-2, i), (i-1, i+1), (i, i+2)
// 注意:中间的(i-1, i+1)不依赖s[i],所以修改s[i]不影响它,不用算
// 只需要算(i-2, i)和(i, i+2)
if (i >= 2) {
if (s[i - 2] == c) add++;
}
if (i + 2 < n) {
if (c == s[i + 2]) add++;
}
// 注意:还要减去原来这两个三元组中,原本就是回文的情况
if (i >= 2 && s[i - 2] == original) add--;
if (i + 2 < n && original == s[i + 2]) add--;
max_add = max(max_add, add);
}
}
cout << base + max_add << endl;
return 0;
}