Make Them Equal 埃氏筛法(1200)

在这里插入图片描述
题意 :

  • 给一长度为n的字符串,进行以下操作,将所有字符都变成字符c :取一个整数 1 < = i < = n 1<=i<=n 1<=i<=n,令所有不被i整除的j有s[j] == c,求最小操作次数

思路 :

  • 如果s全为c,输出0
  • 如果最后一位为c,输出1 n
  • 如果最后一位不为c,从2开始枚举,考虑是否有一个数能将所有字符改为c,优化枚举方案,用类似于埃氏筛的思想,考虑当前这个数的所有倍数在字符串中所对应的字符是否不是c,如果有的话这个数就不合理,这样的复杂度是 O ( n l o g n ) O(nlogn) O(nlogn),可以过
  • 如果有这样的数 输出 1 x
  • 如果没有 输出 2 ,取一个非n因数的任意数(比如 n − 1 n-1 n1,就不需要枚举了)和n
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#define endl '\n'
 
using namespace std;
 
typedef long long ll;

void solve()
{
    
    
    int n;
    char c;
    string s;
    cin >> n >> c >> s;
    
    bool flag = true;
    for (int i = 0; i < n; i ++ )
        if (s[i] != c)
        {
    
    
            flag = false;
            break;
        }
    if (flag)
    {
    
    
        cout << 0 << endl;
        return ;
    }
    
    if (s[n - 1] == c)
    {
    
    
        cout << 1 << endl << n << endl;
        return ;
    }
    
    for (int i = 2; i <= n; i ++ )
    {
    
    
        bool ok = true;
        for (int j = i; j <= n; j += i)
            if (s[j - 1] != c)
            {
    
    
                ok = false;
                break;
            }
        if (ok)
        {
    
    
            cout << 1 << endl << i << endl;
            return ;
        }
    }
    cout << 2 << endl << n - 1 << ' ' << n << endl;
}
 
int main()
{
    
    
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    
    int _ = 1;
    cin >> _;
    
    while (_ -- )
    {
    
    
        solve();
    }
    
    return 0;
}

  • 优化 :考虑证明结论 n的后一半数中,存在某个值不在下标序列中,则这个值可以作为答案。充分性显然成立,必要性考虑n的前一半数如果作为答案,则一定有一个它的倍数属于n的后一半数,且不在下标序列中
  • 上述所有情况都不满足时,输出n和n-1即可消除所有数

猜你喜欢

转载自blog.csdn.net/m0_51448653/article/details/121449400
今日推荐