算法学习入门---算法题DAY5

1.小红的数字分裂

  1. 关键观察

每次分裂操作 x → a + b,数组的总和是不变的 。最终所有元素都等于同一个值 T,因此:

  • 最终元素个数为 k,那么 sum = k × T
  • 每个原始元素 a_i 必须是 T 的倍数(因为 a_i 要被拆成若干个 T)

要让操作次数最少,就要让 k 尽可能小(操作次数 = k - n),等价于让 T 尽可能大。


  1. 核心结论

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;
}
相关推荐
h39748 小时前
DirectShow过滤器开发-视频源过滤器
c++·windows·音视频·directshow
程序猿编码9 小时前
榨干 RTX5090 算力!Qwen3 专用单卡推理引擎,手写C++/CUDA 算子实现 MTP 推测解码
开发语言·c++·大模型推理·qwen3·多模态推理
西飘客10 小时前
vs 怎么根据dll 生成lib文件
c++·qt
程序员老陆11 小时前
深入理解 C++ thread_local:线程私有存储的正确打开方式
开发语言·c++·程序设计
信奥卷王11 小时前
[GESP202609 六级] 分树规划
算法
夏幻灵12 小时前
LeetCode 21:合并两个有序链表——双指针与哑节点详解
算法·leetcode·链表
徐小黑ACG13 小时前
Golang 基础05 结构体struct
开发语言·算法·golang
Navigator_Z14 小时前
LeetCode //C - 1286. Iterator for Combination
c语言·算法·leetcode
北极有牛14 小时前
cpp学习笔记--常量指针
java·开发语言·算法