这段时间请不要找Itst聊天,Itst已经做疯了
事实证明大模拟题不可做
query 1
送分,加起来一起乘即可
I I + 1 2 < 3 1 - 4 O 5
query 2
送分
I - 1 < 2 4 + 2 3 S 4 O 5
query 3
送分,把原数扩大$INF$倍,再调用$s$函数即可
默认下面的$INF=2^{100}$
I < 1 100 S 2 C 3 -0.5 < 4 1 O 5
query 4
好火啊qaq
因为我们的操作只允许我们放大到无穷大和缩小到趋近于$0$,所以我们考虑当$x$趋近于$0$时式子会趋向于什么
因为$s'(x) = ((1+e^{-x})^{-1}) ' = -(1+e^{-x})^{-2} \times (1+e^{-x})'$
$(1+e^{-x}) ' = (e^{-x}) ' = -e^{-x}$
所以$s'(x) = \frac{e^{-x}}{(1 + e^{-x})^2}$
将$0$带入得$s'(0)=\frac{1}{4}$
也就是说当$x$趋近于$0$时,函数可以近似为一个一次函数:$y=\frac{1}{4}x + 0.5$
而$s(x \times INF)$在$x<0$时等于$0$
所以不妨求$s(\frac{x}{INF} + INF \times s(x \times INF))$
如果$x<0$,括号内部的值趋向于$0$,得到的结果为$\frac{x}{4INF}+0.5$,那么取负、加上$0.5$、乘上$8INF$之后得到了$-2x$,加上$x$就得到了$-x$。
如果$x>0$,括号内部的值为$INF$,得到的结果为$1$。那么取负、加上$0.5$、乘上$8INF$、加上$x$之后得到了$4INF + x$,与我们需要的条件不符
那么我们只需要最后减去$4INF \times s(x \times INF)$即可满足条件了
当输入为$0$时会很尴尬地得到$0.5$的结果,我们只需要给$0$加上或减去$eps$就可以了
I C 1 -0.0000000000000000000000001 < 2 100 S 3 < 4 102 > 1 100 + 5 6 S 7 - 8 C 9 0.5 < 10 103 + 1 11 + 5 12 O 13
query 5
送分,模拟题,注意不要对$2^0$项左移即可
freopen("nodes5.out" , "w" , stdout); queue < int > q; int cnt = 0; for(int i = 31 ; i >= 0 ; --i){ puts("I"); ++cnt; if(i) printf("< %d %d\n" , cnt++ , i); q.push(cnt); } while(q.size() > 1){ printf("+ %d " , q.front()); q.pop(); printf("%d\n" , q.front()); q.pop(); q.push(++cnt); } printf("O %d\n" , q.front());
query 6
贼卡常
设$p$为当前数,$k$从$31$到$1$用$query\ 3$的方法检验$p-2^k$是否为正,如果为正减去$2^k$
$k=0$时可以直接输答案,无需判断。
考虑我们每一次使用$query\ 3$的方法时都需要乘上$INF$,常数太大,我们考虑在输入这个数据之后直接乘上$INF$,这样就不用每一次都左移。
使用浮点数计算二进制次幂。
可能会存在$p=2^k$,导致$s((p-2^k) \times INF)=0.5$的情况产生,我们只需要将$2^k -= eps$就不会有这种问题发生了。
freopen("nodes6.out" , "w" , stdout); puts("I"); puts("< 1 100"); int cur = 2; for(int i = 131 ; i > 100 ; --i){ printf("C %d -%.7lf\n" , cur , pow(2.0 , i-0.0001)); printf("S %d\n" , cur + 1); printf("O %d\n" , cur + 2); printf("< %d %d\n" , cur + 3 , i); printf("- %d\n" , cur + 4); printf("+ %d %d\n" , cur , cur + 5); cur += 6; } printf("> %d 100\n" , cur); printf("O %d\n" , cur + 1);
query 7
实际上直接交样例可以在$Luogu$上$AC$,但是$UOJ\ Hack$了
用$query\ 6$的方法拆二进制,如果我们做按位加法,只有$11$不满足我们的要求
也就是说和为$2$时答案为$0$,否则和原来一样
设和为$x$,不难想到$ans=x +(-(s(x - 1.5) \times 2))$
freopen("nodes7.out" , "w" , stdout); queue < int > que1 , que2 , que3; puts("I"); puts("< 1 100"); cur = 2; for(int i = 131 ; i > 100 ; --i){ printf("C %d -%.7lf\n" , cur , pow(2.0 , i-0.0001)); printf("S %d\n" , cur + 1); que1.push(cur + 2); printf("< %d %d\n" , cur + 2 , i); printf("- %d\n" , cur + 3); printf("+ %d %d\n" , cur , cur + 4); cur += 5; } printf("> %d 100\n" , cur); que1.push(cur + 1); puts("I"); printf("< %d 100\n" , cur + 2); cur += 3; for(int i = 131 ; i > 100 ; --i){ printf("C %d -%.7lf\n" , cur , pow(2.0 , i-0.00000000001)); printf("S %d\n" , cur + 1); que2.push(cur + 2); printf("< %d %d\n" , cur + 2 , i); printf("- %d\n" , cur + 3); printf("+ %d %d\n" , cur , cur + 4); cur += 5; } printf("> %d 100\n" , cur); que2.push(cur + 1); ++cur; for(int i = 31 ; i >= 0 ; --i){ printf("+ %d %d\n" , que1.front() , que2.front()); ++cur; que1.pop(); que2.pop(); printf("C %d -1.5\n" , cur++); printf("< %d 200\n" , cur++); printf("S %d\n" , cur++); printf("< %d 1\n" , cur++); printf("- %d\n" , cur++); printf("+ %d %d\n" , cur - 5 , cur); ++cur; if(i) printf("< %d %d\n" , cur++ , i); que3.push(cur); } while(que3.size() > 1){ printf("+ %d " , que3.front()); que3.pop(); printf("%d\n" , que3.front()); que3.pop(); que3.push(++cur); } printf("O %d\n" , que3.front());
query 8
考虑找到一个点$x0$使得$s'(x0)=0.1$
然后用跟$query\ 4$相似的方法,将$\frac{x}{INF}+x0$代入$s$就可以得到$0.1x0 + 0.1\frac{x}{INF}$
然后还原就可以了
关于这个$x0$我是直接蒯的数据可以二分求上面导数式子的零点
freopen("nodes8.out" , "w" , stdout); puts("I"); puts("> 1 96"); puts("C 2 -0.9624236501192068949955178268487368462703686687713210393220363376803277"); puts("S 3"); puts("C 4 -0.2763932022500210303590826331268723764559381640388474275729102754589479"); puts("< 5 95"); puts("O 6");
query 9
使用冒泡排序(虽然我自己写的冒泡排序不知道怎么无限$WA$)
伪代码长这样:
for i 1 -> 16 for j i+1 -> 16 t = val[i] + val[j]; val[j] = min(val[i]-val[j] , 0) + val[j]; val[i] = t - val[j];
然后考虑如何实现上面的min函数
跟$query\ 4$的实现很像:求$s(\frac{x}{INF} + INF \times s(x \times INF))$,减$0.5$,乘$4INF$,减$s(x\times INF)\times 2INF$即可
freopen("nodes9.out" , "w" , stdout); int num[20] = {}; for(int i = 1 ; i <= 16 ; ++i){ puts("I"); num[i] = i; } cur = 16; for(int i = 1 ; i <= 16 ; ++i){ for(int j = i + 1 ; j <= 16 ; ++j){ printf("+ %d %d\n" , num[i] , num[j]); printf("- %d\n" , num[i]); printf("+ %d %d\n" , num[j] , cur + 2); printf("C %d 0.000000000000000000000000000001\n" , cur + 3); printf("< %d 500\n" , cur + 4); printf("S %d\n" , cur + 5); printf("< %d 151\n" , cur + 6); printf("> %d 150\n" , cur + 3); printf("+ %d %d\n" , cur + 7 , cur + 8); printf("S %d\n" , cur + 9); printf("- %d\n" , cur + 7); printf("C %d -0.5\n" , cur + 10); printf("< %d 152\n" , cur + 12); printf("+ %d %d\n" , cur + 11 , cur + 13); printf("+ %d %d\n" , num[i] , cur + 14); printf("- %d\n" , cur + 15); printf("+ %d %d\n" , cur + 1 , cur + 16); num[i] = cur + 15; num[j] = cur + 17; cur += 17; } } for(int i = 1 ; i <= 16 ; ++i) printf("O %d\n" , num[i]);
query 10
TBC
调$query\ 9$调太久了,不想写了,然后就随便蒯了一份代码把结果蒯了
尾声
这题目真养生~