嘘~ 正在从服务器偷取页面 . . .

洛谷P9034 「KDOI-04」Again Counting Set 题解


洛谷P9034 「KDOI-04」Again Counting Set 题解

题目链接:P9034 「KDOI-04」Again Counting Set

题意

小 S 不喜欢集合,不喜欢自然数,不喜欢求和,不喜欢求积,不喜欢最小值,不喜欢最大值,不喜欢 $\operatorname{mex}$,所以有了这题。

给出 $n,k$,求有多少个可重整数集合 $S$ 满足:

  • $|S|=k$;
  • 对于任意 $x\in S$,$0\le x\le n$;
  • $\displaystyle{\prod_{x\in S} x=\min_{x\in S} x}$;
  • $\displaystyle{\sum_{x\in S} x=\min_{x\in S} x+\max_{x\in S}x+{\operatorname{mex}}(S)}$。

注: $\bf{mex}$ 指集合中没有出现过的最小的自然数。

输入格式

本题包含多组测试数据。

输入的第一行包含一个正整数 $T$,表示测试数据组数。

对于每组测试数据,输入包含一行两个正整数 $n,k$。

输出格式

对于每组测试数据,输出一行一个整数表示答案。

数据范围

对于 $100\%$ 的数据,保证 $1\le T\le10^6$,$1\le n,k\le10^{18}$。

根据条件四可以发现一定有 $k\ge 2$ ,结合条件三则有 $\min x \le 1$ ,考虑分类讨论。

  • 当 $\min x = 1$ 时,条件三说明集合内仅有 $1$ ,结合条件四,该情况只有 $\{1,1\}$ 一种
  • 当 $\min x = 0$ 时,仅需考虑条件四 $\sum x=\max x+\operatorname{mex}(S)$ 。

设 $S$ 所有非最大值且非零的数组成的集合为 $T$ 。

可以发现,随着 $\mathrm{mex}(S)$ 的增长,$\sum_{x \in T} x$ 的值将以 $\mathcal{O}(|S|^2)$ 的速度增长

需要满足 $\mathcal{O}(n^2) \approx \mathcal{O}(n)$ (这个表示不是很严谨)的数量级显然非常小

因此考虑手动枚举一下 $s=\mathrm{mex}(S)$ ,看看是怎么回事。

  • $s=1$ ,无解。
  • $s=2$ ,则 $T=\{1,1\},~S = T \cup \{x\}\cup\{0,0,\cdots,0\}\quad(x=1,3,4,5,\cdots,n)$ 。
  • $s=3$ ,则有两种情况:
    • $T=\{1,2\},~S = T \cup \{x\}\cup \{0,0,\cdots,0\}\quad(x=2,4,5,6,\cdots,n)$
    • $T=\{1,1,1\},~S = T\cup \{2\}\cup \{0,0,\cdots,0\}$ 。
  • $s=4$ ,则 $T = \{1,1,2\}, ~S=T\cup \{3\} \cup \{0,0,\cdots,0\}$ 。
  • $s=5$ ,此时最大值为 $4$ ,则 $\sum_{ x \in T}x$ 的值至少也为 $1+2+3>5$ ,因此无解。
  • $s > 5$ ,此时同理于 $s=5$ ,可证无解。

时间复杂度 $\mathcal{O}(T)$

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)())

void solve()
{
    int n, k, res = 0; cin >> n >> k;
    if(k == 1) return cout << "0\n", void(0);
    if(k >= 4)
    {
        res += 1 + max(0ll, n - 2);
        if(n >= 2) res += 1 + max(0ll, n - 3);
    }
    if(k >= 5)
    {
        if(n >= 2) ++res;
        if(n >= 3) ++res;
    }
    if(k == 2) ++res;
    return cout << res << '\n', void(0);
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int qwq; cin >> qwq; while(qwq--) solve();
    return 0;
}

参考文献

[1] https://www.luogu.com.cn/blog/AlexWei/solution-p9034


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录