QOJ-7236 题解-非构造性证明相关
QOJ-7236 题解-非构造性证明相关
其实这道题只是个引子,我想写的其实是两道数学题。
另外,此时是 2026-3-3 的 19:59 分,作者菌正在火车上传文章,心疼我的流量 QAQ……
题目描述:
给定 \(n\)(保证 \(n\) 为偶数)个集合 \(A_1 \sim A_n\),每个集合恰有 \(n\) 个数,所有集合的并恰有 \(2n\) 个数(即值域为 \(1 \sim 2n\)),要求寻找并输出两个集合,其交集的大小大于等于 $\frac{n}{2} $ 。
(原题有 \(n+1\) 个集合,但是 \(n\) 个够用)
数据范围 \(n \le 6000\)。
part 1
注意到,题目没有要求输出 \(-1\),也就是说保证有解,不妨考虑为什么。
我们可以考虑每两个集合的交集数量之和,即 \(\sum_{1\le i<j\le n} |A_i \cap A_j|\) 的大小。
单独考虑每个元素的贡献,考虑元素 \(i\),假设其出现次数为 \(c_i\),则其对答案的贡献为 \(c_i \choose 2\),即 $\frac{c_i \times (c_i-1) }{2} $,以及 \(\sum c_i=n^2\)。
不难想到,让每个元素出现次数尽可能平均(即对于 \(1\le i\le 2n\),$c_i=\frac{n}{2} $),可以让所有交集大小之和尽可能小,即 \(2n \times \frac{1}{2} \times \frac{n}{2} \times (\frac{n}{2}-1) =\frac{n^2(n-2)}{4}\)。
然后考虑反证法,假设每个交集皆取到最大,任意两个集合的交集大小的和即 $\frac{n\times (n-1)}{2} \times \frac{n-2}{2} = \frac{n \times(n-1) \times (n-2)}{4} $
显然存在 \(\frac{n^2(n-2)}{4}>\frac{n \times(n-1) \times (n-2)}{4}\),根据抽屉原理,必然存在两个集合的交集大小大于等于 $\frac{n}{2} $。
到此为止,后面的其实很自然了。
part 2
我们不能暴力枚举任意两个集合,不妨考虑把这个东西推广。
注意到,如果有一个集合,与其他所有集合分别求交的大小之后比 $\frac{(n-1)\times (n-2)}{2} $ 大,则剩下的集合中必然存在一个集合与这个集合的交集大小大于 \(\frac{n}{2}\),根据上面的证明必然存在这个集合,具体证明读者自证不难。
然后找到这个集合的方法很简单,直接对每个元素单独计算贡献即可,和上面的分析过程一样。
然后再次遍历其他集合分别与这个集合求交,时间复杂度 \(O(n^2)\)。
Code
//I often reminisce about the past
#include<bits/stdc++.h>
using namespace std;
bool Mst;
#define LL long long
#define For(a,b,c) for(int (a)=(b);(a)<=(c);(a)++)
#define Rep(a,b,c) for(int (a)=(b);(a)>=(c);(a)--)
const int N=6e3+10,M=1.2e4+10,K=100+3,Mod=1e9+7;
const int INF=0x3f3f3f3f;
//const LL INF=0x3f3f3f3f3f3f3f3f,all=1ll;
int n,m,k;
template <typename T> void read(T &a){
char c=getchar();T w=1,f=0;while(c<'0'||c>'9'){if(c=='-') w=-w;c=getchar();}
while(c>='0'&&c<='9') f=f*10+c-'0',c=getchar();a=f*w;
}
template <typename T> void tomin(T &a,const T &b){if(b<a) a=b;}
template <typename T> void tomax(T &a,const T &b){if(a<b) a=b;}
int& modadd(int &a,const int &b,const int &mod=Mod){a+=b;a<0?a+=Mod:a>=Mod?a-=Mod:0;return a;}
int& modsub(int &a,const int &b,const int &mod=Mod){a-=b;a<0?a+=Mod:a>=Mod?a-=Mod:0;return a;}
int& modmul(int &a,const int &b,const int &mod=Mod){a=1ll*a*b%mod;return a;}
int ksm(int a,int b,int mod=Mod){int res=1;while(b){if(b&1) modmul(res,a,mod);modmul(a,a,mod);b>>=1;}return res;}
int inv(int x){return ksm(x,Mod-2,Mod);}
bitset <M> a[N];
int t[M];
int Test=1,C;
void mian()
{
read(n);
For(i,1,n)
{
string s;
cin>>s;
for(int k=0;k<s.size();k++)
{
int d=s[k]-33;
For(j,0,5)
{
int g=(d>>j)&1;
if(g) a[i][k*6+j]=1;
}
}
}
For(i,1,n)
For(j,0,n*2-1) t[j]+=a[i][j];
int hero=0;
For(i,1,n)
{
LL num=0;
For(j,0,n*2-1)
{
num+=a[i][j]*(t[j]-1);
}
if(num>1ll*(n-2)*(n-1)/2) hero=i;
}
For(i,1,n)
{
if(i==hero) continue;
if((a[i]&a[hero]).count()>=n/2)
{
int h2=i;
if(h2<hero) swap(h2,hero);
printf("%d %d\n",hero,h2);
return ;
}
}
}
bool Med;
signed main()
{
cerr<<(&Mst-&Med)/1024.0/1024.0<<" MB\n";
// freopen("debug.in","r",stdin);
// freopen("debug.out","w",stdout);
// cin>>Test;
while(Test--) mian();
return 0;
}
到此为止,这道题已经做完了,后面是数学题部分。
part 3
注意到,上面的证明方法并没有真正找出两个集合,而是证明了必然存在。那么,有没有类似的题目呢?
题目描述:
给定一个平面,询问在这个平面上的任意十个点是否都可以一定数量不相交的任意固定半径的圆覆盖?(即对于任意半径的圆和任意十个点均成立)
特别的,我们认为圆的边缘也算作覆盖,且允许单点相切。
下面有 \(4\) 个提示,强烈建议自己思考一番哦,不会了再去看提示。如果实在不会,不妨顺着提示引导,就像研究特殊性质一样。
提示 1
和上文类似,我们并不需要构造出一种方案,而是证明必然存在即可。
提示 2
类似于上文,我们考虑是否存在“极值”。比如说,圆的“最密铺法”,即将圆的外接正六边形密铺。
(想象不出来可以百度搜一下长什么样)
提示 3
注意到,由于可以平移,所以我们可以直接固定圆,来放点。
提示 4
不妨考虑一种固定的圆的铺法,平移整个平面圆,来对每个点进行讨论。
证明
考虑将平面用半径为 \(R\) 的圆作正六边形密铺,即圆心位于正三角形网格的格点上,相邻圆心距离为 \(2R\),使得每个圆与六个相邻圆相切。考虑相邻三个圆心组成的正三角形,这个图形的面积为 \(\sqrt 3 R^2\),圆形覆盖面积为 \(\frac{\pi R^2}{2}\),其占比为 \(\frac{\pi R^2}{2\sqrt 3 R^2}=\frac{\pi}{2 \sqrt{3}}\),这个值约等于 \(0.9069\)。
然后我们直接随机十个点,发现被圆覆盖的期望为 \(0.969\),比 \(9\) 要大,也就是必然存在一个为 \(10\) 的方案,即全部被覆盖。
严谨我们随机选取一个向量 \(\vec{v}\),由于这是周期图形,所以 \(\vec{v}\) 的大小有范围,然后考虑这个向量使这十个点均在图形范围内,然后用类似上面的方法证明其概率为正即可。
part 4
还有高手?
给定一个 \(n\) 行 \(m\) 列的矩阵(保证 \(n,m\) 有限)。定义一次操作为:如果该点仍然存在,则可以选择该点,并移除其右下角所有点。拿走左上角那个点的人输。Alice 和 Bob 轮流操作,Alice 先手,请问 Alice 是否有必胜策略。
另外的,如果 \(m\) 变为 \(\infty\),这个策略是否可行?
另外的,如果 \(n,m\) 均为 \(\infty\),在问题二的基础上,则先手是否有必胜策略?
注意:与一般 OI 题不同,我们不需要构造方案。
提示
有一道好玩的数学题,大概是:能否找到请两个无理数 \(a,b\),使得 \(a^b\) 为有理数。
证明很简单:设 $a=\sqrt{2}^{\sqrt{2}} $,若 \(a\) 是有理数,则命题得证,否则取 \(a^{\sqrt 2}=\sqrt{2}^{\sqrt{2}\times\sqrt{2}}=\sqrt{2}^2=2\),则命题得证。
证明:
我们将左上角标号 \((1,1)\),右下角标号 \((n,m)\),考虑 Alice 操作:
如果 \(n=1,m=1\),先手必败。
否则,尝试取 \((n,m)\),然后考虑 Bob:
若 Bob 必胜,则此时必然存在一个策略使得先手必胜,Alice 直接抢走 Bob 的策略即可;反之,则 Alice 必胜。
但倘若 \(m\) 变为 \(\infty\),则不存在右下角,比如 Alice 取了 \((x,y)\),Bob 的必胜策略是 \((x-1,y+1)\),则 Alice 无法模仿 Bob。
但如果 \(n,m\) 均为 \(\infty\),Alice 只要先拿走 \((2,2)\),然后取和 Bob 取的点对称的点即可。

浙公网安备 33010602011771号