论一条咸鱼是有多闲系列。
浑浑噩噩做了两天,感觉自己造计算机的水平得到了本质上的提升。
官方题解看不懂啊喂,民间题解在哪找啊喂。

test1

非常简单。

I
I
+ 1 2
- 3
+ 4 4
O 5

test2

非常简单。

I
< 1 4
+ 1 2
- 3
S 4
O 5

test3

可以利用一下精度的性质。
我们可以将这个a乘以一个很大很大的数,这样,如果它是0,那么S一下的结果就是0.5,如果它大于0,那么S一下就是1,如果小于0就是0.
然后脑补一下怎么把这三个结果处理成-1,0,1的形式就成了。

I
< 1 1000
S 2
C 3 -0.5
+ 4 4
O 5

test4

MAYA这是人做的点吗?Orz VFK太强啦!
考虑利用一下求导的基本手法(虽然咸鱼不会求导),得知当x的绝对值非常小时,s(x)可以近似看作x4+0.5x4+0.5\frac{x}{4}+0.5。
假定这个性质在这个test里面是会被用到的,人类的第六感告诉我们,负数要用这个性质的可能性更大。所以我们先尝试构造一个数ppp,使得当x为正的时候,p" role="presentation">ppp非常大(因为这个非常大一般构造为2k12k12^{k_1}的形式,所以我们姑且认为此时p=2k1p=2k1p=2^{k_1})。而x为负的时候,p=0p=0p=0。
然后我们令y=s(x2k2+p)y=s(x2k2+p)y=s(\frac{x}{2^{k_2}}+p),这样当x为正的时候,y=1y=1y=1,否则x=0.5+x2k2+2x=0.5+x2k2+2x=0.5+\frac{x}{2^{k_2+2}}。
这有什么好处呢?(0.5−y)∗2k2+3=−2x(0.5−y)∗2k2+3=−2x(0.5-y)*2^{k_2+3}=-2x,于是我们就把负数这部分搞完了。
而如果x是正数的话,这样操作以后的结果就是:−2k2+2−2k2+2-2^{k_2+2},我们就要试图把这个东西搞掉。
想起有一个数在x为负数时是0而在x是正数时不是,那就是ppp,所以我们加上一个p要使得−2k2−2=0" role="presentation">−2k2−2=0−2k2−2=0-2^{k_2-2}=0。
那么使得k1=k2+2k1=k2+2k_1=k_2+2即可。
至于ppp怎么构造呢,VFK给出的代码已经说了:

In(x);
p=S((x+1e-30)<<500)<<152;//加上1e-30是为了处理0
y=S((x>>150)+p);
r=x+((-y+0.5)<<153)+p;
Out(r);

呃,所以答案就是这样的,能构造出来真是太强了吧:

I
C 1 0.000000000000000000000000000001
< 2 500
S 3
< 4 152
> 1 150
+ 5 6
S 7
- 8
C 9 0.5
< 10 153
+ 1 11
+ 12 5
O 13

test5

比较简单,直接模拟就好。注意不要进行无效操作(比如将a32" role="presentation">a32a32a_{32}左移0位啦)

#include<bits/stdc++.h>
using namespace std;
#define RI register int
int main()
{freopen("nodes5.out","w",stdout);puts("I"),puts("< 1 31");for(RI i=2;i<32;++i) {puts("I");printf("< %d %d\n",3*(i-1),32-i);printf("+ %d %d\n",3*i-4,3*i-2);}puts("I"),puts("+ 92 93"),puts("O 94");return 0;
}

test6

思路:每次计算一下S((x−2k)∗2500)S((x−2k)∗2500)S((x-2^{k})*2^{500}),就可以获得0和1。
但是每次都左移500位非常浪费节点,可以一开始将x左移500位,然后每次用高精度算出2500+k2500+k2^{500+k}。
这样我们每次求一位,要C一次,S一次,O一次。然后继续变形x,减去其最高位,假设这一位是t(t=0或1),那就是要左移一次t,一次t,x再加上一次-t,一共要进行6次操作。
注意到最后一位可以直接将x右移500位变回来然后输出,就可以节约一点点操作,正好190个节点。
但是这样写了会WA,因为如果某一次x==2kx==2kx==2^{k},那么就算乘极大数最后结果也是0,S(0)=0.5S(0)=0.5S(0)=0.5。
所以我们要把2k2k2^{k}稍微弄小一点点,这样如果x==2kx==2kx==2^{k}算出来就是1了。

#include<bits/stdc++.h>
using namespace std;
#define RI register int
struct node{int len,t[1000];}a[33];
void mul(int o) {int ys=0;for(RI i=1;i<=a[o].len;++i) {a[o].t[i]=a[o].t[i]*2+ys;ys=a[o].t[i]/10,a[o].t[i]%=10;}if(ys) a[o].t[++a[o].len]=ys;
}
void print(int o) {for(RI i=a[o].len;i>=1;--i) printf("%d",a[o].t[i]);puts("");
}
int main()
{freopen("nodes6.out","w",stdout);a[1].len=1,a[1].t[1]=1;for(RI i=1;i<=501;++i) mul(1);for(RI i=2;i<=31;++i) a[i]=a[i-1],mul(i);puts("I");puts("< 1 500");for(RI i=31;i>=1;--i) {int k=(32-i)*6-4;a[i].t[60]=0;printf("C %d -",k),print(i);printf("S %d\n",k+1);printf("O %d\n",k+2);printf("- %d\n",k+2);printf("< %d %d\n",k+4,i+500);printf("+ %d %d\n",k+5,k);}puts("> 188 500");puts("O 189");return 0;
}

test7

思路:首先使用上面那种方法,将两个数的二进制转化出来。由于不用输出,所以一共消耗316个节点,剩余平均每次异或可以使用9个节点。
观察什么叫做异或,发现当这两位加起来为1的时候,结果为1。加起来为2或者为0,结果都是0.设这个和为y.
那么怎么把这个2搞成0呢?显然我们是要利用2比较大这个性质,让某一个东西去减去y.
那么就是用S构造一个当输入1和2的时候输出1,否则输出0的东西。
也就是求一下S((y−0.5)×2500)×2−yS((y−0.5)×2500)×2−yS((y-0.5)\times 2^{500}) \times 2-y。
数一下发现正好是9次操作,由于左移0位没有意义之类的,我们还可以节约几次操作呢。

#include<bits/stdc++.h>
using namespace std;
#define RI register int
struct node{int len,t[1000];}a[33];
void mul(int o) {int ys=0;for(RI i=1;i<=a[o].len;++i) {a[o].t[i]=a[o].t[i]*2+ys;ys=a[o].t[i]/10,a[o].t[i]%=10;}if(ys) a[o].t[++a[o].len]=ys;
}
void print(int o) {for(RI i=a[o].len;i>=1;--i) printf("%d",a[o].t[i]);puts("");
}
int main()
{freopen("nodes7.out","w",stdout);int now=0,las=0;a[1].len=1,a[1].t[1]=1;for(RI i=1;i<=501;++i) mul(1);for(RI i=2;i<=31;++i) a[i]=a[i-1],mul(i);puts("I"),puts("I");puts("< 1 500"),puts("< 2 500"),now=4;for(RI i=31;i>=1;--i) {a[i].t[60]=0;int k1=(i==31?3:(30-i)*10+9),k2=(31-i)*10+4;printf("C %d -",k1),print(i),++now;printf("S %d\n",now),++now;printf("- %d\n",now),++now;printf("< %d %d\n",now,i+500),++now;printf("+ %d %d\n",now,k1),++now;printf("C %d -",k2),print(i),++now;printf("S %d\n",now),++now;printf("- %d\n",now),++now;printf("< %d %d\n",now,i+500),++now;printf("+ %d %d\n",now,k2),++now;}puts("> 309 500"),puts("> 314 500"),now=316;for(RI i=31;i>=0;--i) {int k1=(i==0?315:(31-i)*10+6),k2=(i==0?316:(32-i)*10+1);printf("+ %d %d\n",k1,k2),++now;printf("C %d -0.5\n",now),++now;printf("< %d 500\n",now),++now;printf("S %d\n",now),++now;printf("+ %d %d\n",now,now),++now;printf("- %d\n",now-4),++now;printf("+ %d %d\n",now,now-1),++now;if(i!=0) printf("< %d %d\n",now,i),++now;if(i!=31) printf("+ %d %d\n",las,now),++now;las=now;}printf("O %d\n",las);return 0;
}

test8

呃,根据求导的特性,当x很小的时候,拟合一种斜率,使得S(x)−S(0)x=0.1S(x)−S(0)x=0.1\frac{S(x)-S(0)}{x}=0.1,就可以很方便地解决该题。
那么我们把x除以一个很大的数,然后再加上一个数k,现在我们求使得S(k)−S(0)k=0.1S(k)−S(0)k=0.1\frac{S(k)-S(0)}{k}=0.1成立的k,就可以近似算出0.1k+0.1×x2d0.1k+0.1×x2d0.1k+0.1 \times \frac{x}{2^{d}}了。
如何求这个k呢?考虑利用checker三分法求解。
虽然这样理论可行,但是我太菜了愣是搞了一个小时没搞出来,所以偷偷抄了洛谷的题解QAQ

I
> 1 96
C 2 -0.962423650119206894995517826848736846270368668771321039322036337680327735216443548824018858
S 3
C 4 -0.276393202250021030359082633126872376455938164038847427572910275458947907436219510058558559
< 5 95
O 6

test9

使用冒泡排序。
比较两个数a,b,使小的在前,大的在后,出题人已经构造了一种方法:

t=a+b;
a=min(b-a,0)+a;
b=t-a;

然后这个min(x,0)的做法可以参照第4个测试点:

p=S((x+1e-30)<<500)<<152;
y=S((x>>150)+p);
r=(((y-0.5)<<153)-p)>>1;

嗯,就是这样。

#include<bits/stdc++.h>
using namespace std;
#define RI register int
int b[20],now,BAS=16;
int main()
{freopen("nodes9.out","w",stdout);for(RI i=1;i<=BAS;++i) puts("I"),b[i]=i,++now;for(RI i=1;i<BAS;++i)for(RI j=1;j<=BAS-i;++j) {int t,x,p,y,r,ka;printf("+ %d %d\n",b[j],b[j+1]),++now,t=now;//tprintf("- %d\n",b[j]),++now,ka=now;//-aprintf("+ %d %d\n",b[j+1],ka),++now,x=now;//b-aprintf("C %d 0.00000000000000000000000000001\n",x),++now;printf("< %d 500\n",now),++now;printf("S %d\n",now),++now;printf("< %d 152\n",now),++now,p=now;//pprintf("> %d 150\n",x),++now;printf("+ %d %d\n",now,p),++now;printf("S %d\n",now),++now,y=now;printf("C %d -0.5\n",y),++now;printf("< %d 153\n",now),++now;printf("- %d\n",p),++now;printf("+ %d %d\n",now,now-1),++now;printf("> %d 1\n",now),++now,r=now;//rprintf("+ %d %d\n",r,b[j]),++now,b[j]=now;printf("- %d\n",now),++now;printf("+ %d %d\n",t,now),++now,b[j+1]=now;}for(RI i=1;i<=BAS;++i) printf("O %d\n",b[i]);return 0;
}

test10

考虑用一个类似于快速幂的“快速乘”来实现。
那么首先把b转化为2进制,然后如果这一位是1,就加上a×2ka×2ka \times 2^k。
考虑用一个类似于test4的方法来实现这个功能。
设bk为b的第k位,先算出y=S((bk-1)<<500)+(a>>150));,如果bk=0,则y=0,否则y=a2152+12y=a2152+12y=\frac{a}{2^{152}}+\frac{1}{2}。
然后算r=(y*2-bk)<<151,这样如果bk=0就是0,否则就是a,就可以很方便地计算了。
至于取模,可以利用test3的那个函数,a−m∗2ka−m∗2ka-m*2^k大于0时等于1,否则等于0.然后等于1时减m∗2km∗2km*2^k,否则减0,利用以上操作实现。

#include<bits/stdc++.h>
using namespace std;
#define RI register int
struct node{int len,t[1000];}a[33];
void mul(int o) {int ys=0;for(RI i=1;i<=a[o].len;++i) {a[o].t[i]=a[o].t[i]*2+ys;ys=a[o].t[i]/10,a[o].t[i]%=10;}if(ys) a[o].t[++a[o].len]=ys;
}
void print(int o) {for(RI i=a[o].len;i>=1;--i) printf("%d",a[o].t[i]);puts("");
}
int ka,kb,kc,re,now,BAS=31;
int b[35];
void prework() {//转二进制puts("< 2 500"),++now;for(RI i=BAS;i>=1;--i) {a[i].t[60]=0;printf("C %d -",now),print(i),++now;printf("S %d\n",now),++now,b[i]=now;printf("- %d\n",now),++now;printf("< %d %d\n",now,i+500),++now;printf("+ %d %d\n",now,now-4),++now;}printf("> %d 500\n",now),++now,b[0]=now;
}
void mul() {//乘法for(RI i=0;i<=BAS;++i) {int t;printf("C %d -1\n",b[i]),++now;printf("< %d 500\n",now),++now;printf("> %d 150\n",ka),++now;printf("+ %d %d\n",now,now-1),++now;printf("S %d\n",now),++now;printf("+ %d %d\n",now,now),++now;printf("- %d\n",b[i]),++now;printf("+ %d %d\n",now,now-1),++now;printf("< %d 151\n",now),++now,t=now;if(re) printf("+ %d %d\n",re,t),++now;re=now;printf("+ %d %d\n",ka,ka),++now,ka=now;}
}
void mo() {//取模for(RI i=BAS*2+1;i>=0;--i) {int orz,t;printf("< %d %d\n",kc,i),++now,t=now;printf("+ %d %d\n",re,now),++now;printf("C %d 0.5\n",now),++now;printf("< %d 500\n",now),++now;printf("S %d\n",now),++now,orz=now;printf("C %d -1\n",orz),++now;printf("< %d 500\n",now),++now;printf("> %d 150\n",t),++now;printf("+ %d %d\n",now,now-1),++now;printf("S %d\n",now),++now;printf("+ %d %d\n",now,now),++now;printf("- %d\n",orz),++now;printf("+ %d %d\n",now,now-1),++now;printf("< %d 151\n",now),++now;printf("+ %d %d\n",re,now),++now,re=now;}printf("O %d\n",re);
}
int main()
{freopen("nodes10.out","w",stdout);a[1].len=1,a[1].t[1]=1;for(RI i=1;i<=501;++i) mul(1);for(RI i=2;i<=31;++i) a[i]=a[i-1],mul(i);puts("I"),puts("I"),puts("I"),ka=1,kb=2;puts("- 3"),kc=now=4;prework();mul();mo();return 0;
}

总结

  1. 哈哈哈哈我没疯放开我我怎么可能做一道旷野造计算机就疯了呢哈哈哈哈
  2. litble真的是闲的蛋疼。
  3. 巧妙利用减大的数会比较小,减小的数会比较大的性质。
  4. 扯清楚每次操作的上一个节点是什么很重要。
  5. 巧妙利用S的性质。
  6. 真爱生命,远离旷野大计算。

UOJ224/洛谷P1737 【NOI2016】旷野大计算 造计算机相关推荐

  1. [NOI2016]旷野大计算

    Subtask0 造计算机神题.给一个忠告:珍爱生命,远离旷野大计算...... 代码在这里:戳我 Subtask1 给定\(a,b\):求\(-2a-2b\). 熟悉操作环境:\([-(a+b)]& ...

  2. UOJ224 NOI2016 旷野大计算 构造、造计算机

    传送门--UOJ 传送门--Luogu 这段时间请不要找Itst聊天,Itst已经做疯了 事实证明大模拟题不可做 query 1 送分,加起来一起乘即可 I I + 1 2 < 3 1 - 4 ...

  3. 「UOJ224」「NOI2016」旷野大计算

    题目描述 随着人类计算机技术的发展,计算机的能力不断提升,让跳蚤国王非常羡慕. 终于有一天,跳蚤国王发布政令:大力发展跳蚤国的计算机产业!然而,跳蚤国尚未进行工业革命,无法制造出电子计算机所需的元器件 ...

  4. [JZOJ4763] 【NOIP2016提高A组模拟9.7】旷野大计算

    题目 题目大意 给你一个数列,有很多个询问,询问一段区间内,某个数乘它的出现次数的最大值,也就是带权众数. 思考历程 第一次看到这道题,立马想到了树套树之类的二位数据结构,发现不行.(就算可以也很难打 ...

  5. 洛谷刷题笔记 乘方计算

    题目描述 给出一个整数 a 和一个正整数 n,求乘方 a^n. 输入格式 一行,包含两个整数 a 和 n.-−1000000≤a≤1000000,1≤n≤10000. 输出格式 一个整数,即乘方结果. ...

  6. 【JZOJ4763】【NOIP2016提高A组模拟9.7】旷野大计算

    题目描述 输入 输出 样例输入 5 5 9 8 7 8 9 1 2 3 4 4 4 1 4 2 4 样例输出 9 8 8 16 16 数据范围 解法 离线莫队做法 考虑使用莫队,但由于在删数的时候难以 ...

  7. noi2016旷野大作战

    玩了差不多两个小时61分 大概第9个点可以再拿5-6分 但是挺麻烦的并不想搞.. 这道题还是比较考验智商的??以及对那个特殊的ln函数的应用 感觉题目出的挺好的 看了题解 发现第4个点的确我应该想不到 ...

  8. NOIP提高组 旷野大计算

    Description Data Constraint Solution 对于这种区间查询的题,我们直接上莫队,用堆处理一下就可以用O(NN−−√logN\sqrt{N}logN)的时间卡过去. 代码 ...

  9. 【NOIP模拟】旷野大计算

    Description **Solution 这是一道套路题,不过我现在才学会套路. 对于莫队算法,进队统计答案很快,出队统计答案很慢的情况有一个套路:把所有的出队变成进队,每次询问的[l,r],把l ...

最新文章

  1. Nginx学习3:反向代理实例
  2. 去了两家外包公司,颠覆了我的认知!
  3. idea maven PKIX path building failed
  4. python读取本地文件-python解析本地HTML文件
  5. 《leetcode》search-insert-position
  6. 关于LayoutParams
  7. 关于互斥锁,条件变量的内核源码解析
  8. 8位16进制频率计设计实验--VHDL
  9. pycharm Debug调试
  10. Python:体脂计算
  11. 两个excel表格取交集_(怎么用excel把两个表格数据做交集)如何把不同excel表格数据取交集...
  12. hp服务器修改阵列,HP服务器阵列配置教程(适合初学者)
  13. MongoDB中的_id和ObjectId
  14. 机器学习之模型评估方法总结
  15. c语言提供了三种预处理命令,9、C语言之预处理命令
  16. 关于css设置元素垂直水平居中的问题
  17. Brendan Eich 谈 Javascript 的起源
  18. ArchieOpenGL教程第11课:使用位图字体 在屏幕上显示字体
  19. Detection论文总结(2)AutoFocus: Efficient Multi-Scale Inference
  20. 12.郝斌C语言笔记——枚举

热门文章

  1. 计算思维导论-为什么要学习计算思维
  2. CANoe.DiVa 操作指南 - 时间参数配置
  3. CANoe和CANoe.DiVa关于通信测试的简略汇总
  4. [转载] 晓说——第11期:揭秘我党历史上最危险的叛徒
  5. 基于树莓派的Azure物联网实践(一)
  6. 突发!中国顶级程序员左耳朵耗子(陈皓)去世
  7. 游戏直播软件测试工程师,【斗鱼TV软件测试工程师面试】斗鱼软件测试面试经验。-看准网...
  8. 数据库打开数据表_使用微数据打开您的数据
  9. .Net 7 CLR和ILC编译函数过程
  10. 华为无线-Portal认证异常-无线强制切换为手机流量