题意 :
- 给一长度为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 n−1,就不需要枚举了)和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即可消除所有数