CF #764 Div.3(B ~D)

这篇博客探讨了三个算法问题:如何通过调整数列元素构造等差数列,如何通过除2操作形成1~n的序列,以及如何找到最短回文字符串。涉及关键步骤包括分类讨论、集合操作和动态规划策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CF #764 Div.3

B题 Make AP

给定a b c

使其中一个数 乘 任意正整数m 问是否能构成成差数列

我们可以想到等差数列的性质
2b=a+c 2b = a + c 2b=a+c

思路:分类讨论 a b c的三种情况
- 2b = a + c 直接构成等差数列
- 2b < a + c 说明b偏小了 (a + c) % (2 * b) == 0 ? YES : NO
- 2b > a + c 说明a或者c偏小了 ( (2b - a) % c == 0 || (2b - c) % a == 0 ) ? YES : NO
int main()
{
    std::ios::sync_with_stdio(false);cin.tie(0);
    int t;
    cin >> t;
    while(t--)
    {
        int a, b, c;
        cin >> a >> b >> c;
        if(2 * b == a + c)  cout << "YES" << endl;
        else if(2 * b < a + c) 
        {
            if((a + c) % (2 * b) == 0)    cout << "YES" << endl;
            else cout << "NO" << endl;
        }
        else if(2 * b > a + c)   
        {
            if( (2 * b - a) % c == 0 || (2 * b - c) % a == 0 )   cout << "YES" << endl;
            else cout << "NO" << endl;
        }
    }
    return 0;
}

题C Division by Two and Permutation

给n个数 我们可以对任意一个数做除2操作 问是否能构成一个1~n的序列

思路: 用STL的set做很容易理解,每输入一个数,当它大于n时除以2,小于n时判断set中是否有该数,
若没有insert到set中,若有则继续除以2,若该数对于set中的数没有任何贡献,则必不满足条件。
int main()
{
    std::ios::sync_with_stdio(false);cin.tie(0);
    int t;
    cin >> t;
    while(t--)
    {
        set<int> s;
        bool flag = true;

        int n;
        cin >> n;

        for(int i = 1; i <= n; i++)
        {
            int x;
            cin >> x;
            while(x > n)    x /= 2;
            while(s.count(x))   x /= 2;//已存在于集合当中
            if(x == 0)  flag = false;//如果你一路除下来 你都不能成为序列中的一部分 就必然不能构成序列了
            else s.insert(x);
        }
        cout << (flag ? "YES" : "NO") << endl;
    }
    return 0;
}

题D Palindromes Coloring

给定字符串s,返回可以通过交换任意两个字符而形成的最短回文字符串的最长长度,但是必须将字符串分割成k个回文字符串

思路:因为提到了最短回文字符串 且一共有k个回文字符串 那么我们首先要想的就是尽量让回文字符串的长度平均 
我们首先要从回文的定义入手 回文字符串 意味着对称字符的出现 
将成对的字符平均分给k个回文字符串
剩下的多出来的字符 和 之前单个的字符 相加 若是大于k 
最短字符串长度加一
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);
    cin >> t;
    while(t--)
    {
        int n, k;
        cin >> n >> k
        cin >> s;
        ms(letter, 0);
        for(int i = 0; i < s.size(); i++)   
            letter[s[i] - 'a'] ++;
        
        int tot1 = 0, tot2 = 0;
        for(int i = 0; i < 26; i++)
        {
            tot1 += letter[i] / 2;
            tot2 += letter[i] % 2;
        }

        int res = tot1 / k * 2;//成对的字母数量 / 子串数量
        if(tot1 % k * 2 + tot2 >= k )	res ++;
        cout << res << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值