题
给定一正整数 ( ),求是否存在一个集合的集合 满足:
- 且 ,
- , 中存在恰好两个不同的集合 满足 且
如果存在这样的集合
,请先输出 “Yes” (不含引号),
然后接下来一行输出一个正整数表示
。
接下来
行,每行先一个正整数,表示集合中的第
个元素
的大小
。
接下来
个正整数,表示
中的元素。
如果不存在满足条件的集合
,请输出“No”(不含引号)。
你只需要按照如上方法输出一个满足条件的
即可。
输入:3
输出:
Yes
3
2 1 2
2 1 3
2 2 3
解
构造题。考场上不会证明,只会瞎猜。
手玩小数据,发现
可以,
可以,
可以,自然会想是不是满足
的数都可以。然后这类数有个好听的名字叫三角形数1,所以我就画了这样的三角形:
然后发现可以这样分:
(每个颜色代表一个集合)
这貌似是一种通解,于是我就写了这个代码,就过了,代码如下:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define R register
#define Maxn 100005
int main()
{
R int n,sum=0;
scanf("%d",&n);
for (R int i=1;i<=n;++i)
{
sum += i;
if(sum == n)
{
puts("Yes");
printf("%d\n",i+1);
R int j=1,cnt1=2;
for (;j<=n;j+=cnt1,cnt1++)
{
printf("%d ",i);
for (R int k=j-cnt1+2;k<=j;++k)printf("%d ",k);
R int cnt2=cnt1-1;
for (R int k=j+cnt2;k<=n;++cnt2,k+=cnt2)printf("%d ",k);
puts("");
}
j=1,cnt1=2;
printf("%d ",i);
for (;j<=n;j+=cnt1,cnt1++)printf("%d ",j);
return 0;
}
}
puts("No");
return 0;
}
证明
但是我们不能只满足于猜结论!我们要严格证明!
我们接下来证明两个分结论,从而证明原题结论。
三角形数一定能构造出符合条件的集合T
引理1:若
可以构造,并且构造出来的
,那么
一定可以构造。
引理1证明:
设前者构造出来的集合组为
我们按照如下方法给每个集合添加一个数字
我们添上的数都是两两不同的,所以这些集合还是满足两两公共元素恰好 1 个。
接下来,我们添的那些元素还要满足恰好出现在 2 个集合中,于是我们再构造一个集合
这个集合和前面
个集合的公共元素也都是恰好 1 个,并且
这些数都恰好出现在 2 个集合中。因此这是一种合法的构造方案,因此引理1得证。
然后我们知道对于
显然可以构造出
的满足条件的
,这样我们根据数学归纳法就证明了原命题。
不是三角形数一定无法构造出满足条件的集合T
对于一个确定的
,假设能构造出集合
分析可知,
,其中
又根据已知条件,
联立,即
,得
可以证明当且仅当
为三角形数的情况下
为整数,也就是说若
不为三角形数,则不存在符合条件的
。
因此原命题得证。