题解:CF2156C Maximum GCD on Whiteboard
这题就很数学了,很练思维。
首先当一个数是
然后给出一些结论:
- 我们完全可以先删除数再分裂数,答案不会更劣。
- 设我们要使所有数都是
g 的倍数,对于一个数x 它如果\ge 4g ,那它一定可以通过分裂来使得分成的两个数都是g 的倍数。 - 如果
x < 4g ,并且x 不是g 的倍数,那么x 一定没有办法通过分裂来使得分成的两个数都是g 的倍数,所以只能删除。
然后来证明:
- 采用反证法,假设有一个最优解,对于某个数
x ,它将x 分成了x_1,x_2,x_3 ,然后删除了x_1 或x_3 ,那么我们完全可以先删掉x ,然后就不会有分裂操作,这样的话这个序列相当于少了一个数(x_1 或x_2 ),对于这道题,少了一个数只可能更优或相等,但不会更劣。 - 我们完全可以将
x 拆成(g,g+x \bmod g,x-2g-x \bmod g) ,然后很显然满足g \le g+x \bmod g \le x-2g-x \bmod g ,并且g 和x-2g-x \bmod g 显然都是g 的倍数。 - 使用数学归纳法,设
P_x 表示这个命题对于x 的真假,那么P_1 肯定成立,因为1 无法分割,那么考虑P_x ,并且\forall_{i(1 \le i \le x-1)} P_{i} = 1 ,当然2 \le x < 4g,x \not\equiv 0 \pmod g ,因为如果x \ge 4g 或者x \equiv 0 \pmod g ,那P_x 自然成立(前面已经证明),没意义。假设我们将x 分成x_1,x_2,x_3 ,并且x_1+x_2+x_3 = x ,那根据前面说的,P_{x_1} 和P_{x_3} 都是无法分割使得分成的两个数都是g 的倍数,所以想要证反,只有可能x_1 和x_3 都是g 的倍数,如果x_1 \ge 2g ,则x_3 \ge x_2 \ge x_1 ,那么x = x_1+x_2+x_3 \ge 2g+2g+2g \ge 6g ,显然和x<4g 矛盾,因此,唯一的可能是x_1 = g 。假设x_3 = g ,那么根据x_1 \le x_2 \le x_3 得出x_1 = x_2 = x_3 = g ,那么x = 3g ,与x 不是g 的倍数矛盾。最后就是x_3>2g ,于是x = x_1+x_2+x_3 \ge g+g+2g = 4g ,与x<4g 矛盾。
证明完后, 你会发现,对于一个
然后你会发现可以用一个桶来记录每个数出现次数,那么就解决了第
所以说遍历
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
int a[N];
int pre[N];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int _;
cin >> _;
while(_--)
{
int n,k;
cin >> n >> k;
for(int i = 1;i<=n;++i)
{
a[i] = 0;
}
for(int i = 1;i<=n;++i)
{
int x;
cin >> x;
++a[x];
}
for(int i = 1;i<=n;++i)
{
pre[i] = pre[i-1]+a[i];
}
int ans;
for(int i = 1;i<=n;++i)
{
if(n-pre[min(n,(i<<2)-1)]+a[i]+((i<<1)>n?0:a[i<<1])+(i*3>n?0:a[i*3])>=n-k)
{
ans = i;
}
}
cout << ans << '\n';
}
return 0;
}