又是被血虐的一天,
莫名的感觉到了自己的渺小~~
为了保护版权,题面只给出网站链接,敬请谅解。
小K与集合
题面链接
【解析】
由于子集的选择是随机的,因此若要存在划分方案,我们就必须保证无论选哪个子集最后都能得到 0 0 0 。
假如当前我们木有得到 0 0 0 ,集合的大小却小于 k k k 了,那么就不存在合法方案,因为接下来的划分必定会有空集,而一旦有了空集,我们就永远也不可能得到 0 0 0 ,所以输出 0 0 0 。
我们可以考虑数据中给出的特殊情况:初始集合所有元素均相等。
- 假如所有元素都是 1 1 1 ,则至少要有 k k k 个 1 1 1 ,才会有合法方案。
- 假如所有元素都是 2 2 2 ,我们先考虑有 k k k 个 1 1 1 ,再由这些区间得到 0 0 0 。那么要得到这 k k k 个 1 1 1 ,就至少要有 k k k 个 2 2 2 才能得到一个 1 1 1 ,所以至少要有 k 2 k^2 k2 个 2 2 2 ,才会有合法方案。
- 同理可得,如果全是 3 3 3 ,那么至少要有 k k k 个 3 3 3 才能得到一个 2 2 2 ,所以至少要有 k 3 k^3 k3 个 3 3 3 ,才会有合法方案。
综上,我们可以总结出这样一个结论: k 个 i ⇔ ( i − 1 ) k\ 个\ i\ \Leftrightarrow\ (i-1) k 个 i ⇔ (i−1) 。(很像进制对吧?)
所以我们 n n n 向 0 0 0 推一遍,相当于做一次 k k k 进制的进位,如果进到最高位 0 0 0 时最高位上有数字,说明存在合法方案,否则就不存在,输出 0 0 0 即可。
接下来我们进行集合的划分。如果要存在合法方案,那么初始集合里至少要有 1 个 1 , k 个 2 , k 2 个 3 … 1\ 个\ 1\ ,\ k\ 个\ 2\ ,\ k^2\ 个\ 3… 1 个 1 , k 个 2 , k2 个 3… ,然后它们会全部减 1 1 1 。
最后只要顺着推过去即可。
时间复杂度: Θ ( n ) \Theta(n) Θ(n) 。
有个更详细的讲解:(盗个图)
【参考代码】
#include<bits/stdc++.h>
#define ll long long
#define ud using namespace std
ud;
const int maxn=1e5+1000;
int T,n,k,a,b[maxn],c[maxn];
ll cnt=1,sum=1,tot=1;
vector<int> id[maxn],ans[maxn];
inline long long read()
{
long long sum=0,flag=1;
char c;
for(