人类智慧导论——最优化问题杀手
L_Hospital_ · · 个人记录
作为人类,发扬人类智慧是我们的光荣职责。
我们应该坚信,在最优化问题中,出题人往往缺乏全面人类智慧,甚至完全缺乏人类智慧。三个oier,顶个dinner。我们充分发扬人类智慧,想出精密的乱搞做法,跳开出题人的人类智慧范畴,终能让我们走向胜利✌️。(AK就别想了,这不是正解)
下给出人类智慧举例:(按时间顺序)
1、zr2023noip d2T3
题面:1e6次询问,每次给出n=xp^2,其中p是质数。求正整数a,b,c使得n=ab+ac+bc,或报告无解。开subtask。
老哥的想法(对代码瞪眼出来的,可能有误):可以发现大多数情况都是有解的,并且可以手动构造,于是把能想到的比较好的手动构造方法放一起,并尝试a,b很小的情况。
开了subtask+多测也不要怕,后来发现每个sub就一个点。
结果:小sub挂了,80pts后三个sub都过了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int t;
ll x,p,s;
int main(){
scanf("%d",&t);
while(t--){
scanf("%lld%lld",&x,&p);
if(x>=p){
printf("%lld %lld %lld\n",p,x+1-p,p*p-p);
continue;
}
if(p==2){
puts("-1");
continue;
}
s=1;
while(x%4==0){
x/=4;
s*=2;
}
if(x%2==1){
ll a=1,b=1,c=(x*p*p-1)/2;
printf("%lld %lld %lld\n",a*s,b*s,c*s);
continue;
}
if(x==2){
ll a=1,b=2,c=2*(p*p-1)/3;
printf("%lld %lld %lld\n",a*s,b*s,c*s);
continue;
}
bool vis=0;
for(int i=1;i<=100;i++){
for(int j=i;j<=100;j++){
ll k=(x*p*p-i*j)/(i+j);
if(k*(i+j)+i*j==x*p*p){
printf("%lld %lld %lld\n",i*s,j*s,k*s);
vis=1;
break;
}
}
if(vis)break;
}
}
return 0;
}
另一位老哥pollard-rho冲过了……代码比较【数据删除】,遂不放。
结论:我们要勇于突破信息学竞赛的天花板,天马行空,就是胜利✌️。
2.国庆某日。
题面:【数据删除】。输出yes或no。计算几何问题。多测,不开sub。
还是那位老哥。可以退火!自己设一个评判函数,变成最优化问题!
获得了55pts的高分。但凡写个数据分治就90了!老哥懊悔不已。
没有代码。
结论:小数据记得写数据分治,有的时候小数据反而容易挂。大多数有的时候出题人懒得多去卡卡,所以也不要怕多测。yes no问题也是可以退火的。
3.CSP前某日
题面:一张无向图,敌人基地在1号点,你要选另一个点,通过【数据删除】的规则计算其他点会被你还是敌人占领。求你最多占领多少点。不开sub。n=1e5.
我的思路:规则中可知你选的点的邻居都会被自己占领,并且之后有优势。所以就选度数最大的1000个点来算。我还拿1号店的前200个领居来算,实则没有一点用。
后面只寄了两个点。可是写的15pts树的数据分治竟然TLE。放OJ上测,十几ms。已经获得了75pts的全场mvp,够了。
没有代码。
结论:大概率是对的东西是值得去发现的。
4.CSP前某日
题面:在n×n的网格中【数据删除】。有一些操作,每次操作完回答yes no。开sub。n=100,n=700,n=5000,n=100000,q<=3e6还有一档有随机性质。
新的一位老哥的思路:网格很大的时候答案大概率是yes。可以,总司令!n<=100写数据分治。
结果:时限5s,删了一些点。没过700,过5000!过随机性质!(虽然随机性质也可以卡,但是出题人有dinner了)
令人忍俊不禁瞬间详见CSP2023游记。
不需要代码。
结论:我们要勇于总司令,出题人没准就是懒了。
5.zr附加赛day3,CF1267H。不开sub。
我的思路:如果一种灯只有一个,那跨过他两边的所有区间都不用再考虑了。所以每次新来一个在k级区间的灯时就给他颜色k,并将这个区间分成左右两个独立的k+1级区间。在随机数据下挺优秀的。
还能更好。一个元素来到一个新区间的时候先lazy在那里,等到第二个元素来了,看哪个元素更接近区间中心,就选哪个元素给颜色k,另一个下放到新分的左右区间去。
再好一点。加入随机化因子。从大到小改变更接近区间中心的元素给颜色k的概率,知道找到解为止。(测下来多了10pts)
结果:80pts的好成绩!排名最高zr比赛。
//promote human intelligence
//create another miracle
#include<bits/stdc++.h>
# define rep(i, j, k) for (int i = j; i <= k; ++i)
# define l(id) tr[id].l
# define r(id) tr[id].r
# define lson(id) tr[id].lson
# define rson(id) tr[id].rson
# define dep(id) tr[id].dep
# define now(id) tr[id].now
using namespace std;
int n, k, p[12105], cnt, d[12105], T;
struct segment
{
int l, r, lson, rson, dep, now;
} tr[2000005];
void kai(int l, int r, int d)
{
tr[++cnt] = (segment) {l, r, 0, 0, d, 0};
}
void add(int id, int u)
{
if (lson(id)) {add(u < now(id) ? lson(id) : rson(id), u); return;}
if (l(id) == r(id)) {now(id) = u; return;}
if (!now(id)) {now(id) = u; return;}
int gdps = (l(id) + r(id)) / 2;
if ((abs(now(id) - gdps) > abs(u - gdps)) ^ (rand() % 1000 < T))
{
kai(l(id), u - 1, dep(id) + 1); lson(id) = cnt;
kai(u + 1, r(id), dep(id) + 1); rson(id) = cnt;
add(now(id) < u ? lson(id) : rson(id), now(id)); now(id) = u;
}
else
{
kai(l(id), now(id) - 1, dep(id) + 1); lson(id) = cnt;
kai(now(id) + 1, r(id), dep(id) + 1); rson(id) = cnt;
add(u < now(id) ? lson(id) : rson(id), u);
}
}
bool solvehumanintelligence()
{
rep(i, 1, cnt) tr[i] = {0, 0, 0, 0, 0, 0};
tr[cnt = 1] = {1, n, 0, 0, 1, 0};
rep(i, 1, n) {add(1, p[i]); if (cnt >= 1900000) return false;}
rep(i, 1, cnt) if (now(i)) {if (dep(i) > k) return false; d[now(i)] = dep(i);}
rep(i, 1, n) cout << d[i] << ' '; return true;
}
void solvehumanhumanintelligence()
{
cnt = 0;
for (T = 1; T <= 500; ++T) if (solvehumanintelligence()) {return;}
}
int main()
{
srand(time(NULL));
// freopen("a.in", "r", stdin);
// freopen("a.out", "w", stdout);
ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
cin >> n >> k;
rep(i, 1, n) cin >> p[i];
// random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);random_shuffle(p + 1, p + n + 1);
if (!solvehumanintelligence()) solvehumanhumanintelligence();
return 0;
}
结论:寻找随机数据下的好方法,也是一种策略。一般情况下很多都是随机数据,不要以为每个都会卡。
祝所有oier智慧出奇迹,将西西弗数据打入信息学竞赛的下水管,取得胜利✌️✌️✌️!