洛谷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\}\) 。
- \(T=\{1,2\},~S = T \cup \{x\}\cup
\{0,0,\cdots,0\}\quad(x=2,4,5,6,\cdots,n)\)
- \(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;
}
参考文献: