一些废话
我知道这道题不难,但不知道为什么,就是写了很多遍,刚开始的时候题目读的是对的,但写着写着就忘了题目原意了,搞笑,然后之后又写了两版,都是将 k 个数字记成总和是 了,之后又看了一遍题目,再改了几下,终于对了
题意
给出一个数组 和一个整数 ,每次可以执行以下操作:
- 标记该数组中每个与其左邻不相等的数字,如所有满足 的
- 要么统一删除满足以上要求的 ,要么统一复制满足以上要求的
保证输入规则:
思路
发现,每次整体删除数字,直到遇到一组出现次数相同的被删完,然后再复制回去才有可能出现新的方案,所以我们先记录每个数字出现的次数,然后保存同一种出现次数对应的数字的个数,这个是为了反推回去,然后我们从 1 开始递增判断出现次数大于等于 的种数。唉,我没招了,我真没招了,我不知道怎么讲才能讲得清楚,所以最后录了个视频,我可是专门为了你,发布了哔站第一个视频啊(呃,其实是为了视频不占内存)
代码
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x & (-x))
#define endl '\n'
typedef long long LL;
#define PLL pair<LL, LL>
const LL MOD = 998244353;
const LL MAX = 1e6 + 100;
const LL INF = 0x3f3f3f3f3f3f3f;
void solve() {
int n, k;
cin >> n >> k;
int sm = 0;
vector<int> a(n + 1, 0), b(n + 1, 0), cnt(n + 1, 0), cnt1(n+ 1, 0);
for (int i = 1; i <= n; ++i) {
int x;
cin >> x;
a[x]++;
sm++;
}
for (int i = 1; i <= n; ++i) {
if (a[i]) {
cnt[a[i]]++;
}
}
vector<int> sf(n + 2, 0);
for (int i = n; i >= 1; --i) {
sf[i] = sf[i + 1] + cnt[i];
}
set<int> res;
for (int i = 1; i <= n && sm >= 0; ++i) {
if (sf[i] != 0 && k >= sm && (k - sm) % sf[i] == 0) {
res.insert(sf[i]);
}
sm -= sf[i];
}
cout << res.size() << endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
LL T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
「一定没有问题的!」
— 魔卡少女樱