旷野大计算
这垃圾语言连个不扣分的乘法都没有...
任务怎么这么鬼畜啊...一个一个点来
第一个点
-2a-2b?-((a+b)*2)即可。
I I + 1 2 + 3 3 - 4 O 5
第二个点
这不就是S(-17a)吗...
S(-(a+(a<<4))即可。
I < 1 4 + 1 2 - 3 S 4 O 5
现在我们有一些操作...是不是感觉手输这些奇怪的指令很不顺手呢
于是我们就写一个C++代码辅助生成一下...
int cnt=0; #define op(s) (cout<<s<<"\n", ++cnt); int input() {return op("I");} int mul2(int p,int cm=1) {return op("< "<<p<<" "<<cm);} int div2(int p,int cm=1) {return op("> "<<p<<" "<<cm);} int cpy(int p) {return op("C "<<p<<" 0");} int add(int a,int b) {return op("+ "<<a<<" "<<b);} int fu(int a) {return op("- "<<a);} int addv(int a,int v) {return op("C "<<a<<" "<<v);} int gs(int a) {return op("S "<<a);} int jian(int a,int b) { int t=fu(b); return add(a,t); } int out(int x) {return op("O "<<x);}
恩所有的不扣分操作都在这了...就这么多
第三个点
计算sgn(a):
奥妙重重啊
稍加考虑,我们可以发现...不用S是做不了的...
那我们考虑用S怎么做。
注意到S在inf时趋近于1,在-inf时趋近于0,在0时趋近于0.5。
只要将a乘上2^2333带入S函数,然后乘2减一即可
out(addv(mul2(gs(mul2(input(),2333))),-1));
就一行 /滑稽
注意到这玩意儿已经可以替代扣分的比较结点啦~
我们定义两个函数吧...
int sgn(int x) {return addv(mul2(gs(mul2(x,2333))),-1);} int gp(int x) {return gs(mul2(x,2333));}
第二个函数p会返回平移前的结果0/0.5/1。
第四个点
计算|x|。
这...我们看看扣分操作...
比较、max和乘法...
sgn(x)*x?要用乘法
max(x,-x)?要用max
这就很尴尬了...看来还是要从这个奇怪的S入手?
我们考虑导数!
当x趋近于0时,$\frac{s(x)-s(0)}{x}=s'(0)=\frac{1}{4}$
一棵赛艇!
这样当|x|充分小时s(x)就≈1/4x+0.5啦。
那我们考虑p(x)(定义在上面第三个点)这个东西当x<0时会返回0...
那么我们就直接带入s(x>>150+p(x)<<2333),这样x>=0时应该s里面会趋近于inf,所以就会变成1,否则就会≈0.5+x>>152。(注意1/4)
那么我们把这玩意儿取负,加上0.5,左移153位,对于x<0显然会变成-2x。x+(-2x)=-x。对于x>=0,带入会变成-0.5<<153,加上这个数就行啦!
啥,怎么加?加上(p(x)/2)<<153=p(x)<<152即可。
咦?你说x=0?x+=1e-30即可。
咦...p(x)<<152...那上面p(x)<<2333我就改成p(x)<<152吧...还可以顺便卡卡常数... 还是再定义一个函数~
int abs(int r) { cout.setf(ios::fixed); cout.precision(30); int x=addv(r,1e-30); int p=gp(x); int py=mul2(p,152); int s=gs(add(div2(x,150),py)); int bf=addv(fu(s),0.5); int m=mul2(bf,153); int ans=add(add(x,m),py); return ans; }
第五个点
进制转换?模拟即可~强行送分
int main() { int s=input(); for(int i=2;i<=32;i++) { s=mul2(s); s=add(s,input()); } out(s); }
第六个点
又是进制转换,把十进制转回二进制?
好主意!
int main() { cout.setf(ios::fixed); cout.precision(30); int s=addv(input(),1e-30); int zero=div2(s,2333); int fone=addv(zero,-1); for(int i=31;i>=0;i--) { int t=mul2(fone,i); int b=gp(add(s,t)); s=add(s,mul2(fu(b),i)); out(b); } }
然而只有8分?或许可以卡卡常?
前两个点先拿个函数存起来好了...
typedef vector<int> vi; vi cv(int s) { cout.setf(ios::fixed); cout.precision(30); addv(s,1e-30); int zero=div2(s,2333); int fone=addv(zero,-1); vi ans; ans.resize(32); for(int i=31;i>=0;i--) { int t=mul2(fone,i); int b=gp(add(s,t)); s=add(s,mul2(fu(b),i)); ans[i]=b; } return ans; } int cv(vi x) { int s=x[0]; for(int i=1;i<32;i++) { s=mul2(s); s=add(s,x[i]); } return s; }
第七个点
计算异或?
那我们只要算00、01、10、11的异或值就行了。
我构不出来...但是出题人构出来了...
int xor01(int a,int b) { int s=add(a,b); int tm=mul2(fu(gp(addv(s,-1.5)))); return add(tm,s); } int main() { freopen("nodes7.out","w",stdout); cout.setf(ios::fixed); cout.precision(30); int a=input(),b=input(); vi va=cv(a),vb=cv(b); vi ans; ans.resize(32); for(int i=0;i<32;i++) ans[i]=xor01(va[i],vb[i]); out(cv(ans)); }
还是8分...算了就这样先弃疗好了。
第八个点
计算a/10?
我们可以对1/10进行二进制分解...
这时候第二题的高精度库就可以派上用场了233
用高精度打个表:
Decimal s=1,cur=0,tar=0.1; int main() { for(int i=1;i<=300;i++) { s/=2; if(cur+s<=tar) cur+=s, cout<<i<<","; } }
然后就可以直接肛了
int list[]={4,5,8,9,12,13,16,17,20,21,24,25,28,29,32,33,36,37,40,41,44,45,48,49,52,53,56,57,60,61,64,65,68,69,72,73,76,77,80,81,84,85,88,89,92,93,96,97,100,101,104,105,108,109,112,113,116,117,120,121,124,125,128,129,132,133,136,137,140,141,144,145,148,149,152,153,156,157,160,161,164,165,168,169,172,173,176,177,180,181,184,185,188,189,192,193,196,197,200,201,204,205,208,209,212,213,216,217,220,221,224,225,228,229,232,233,236,237,240,241,244,245,248,249,252,253,256,257,260,261,264,265,268,269,272,273,276,277,280,281,284,285,288,289,292,293,296,297,300}; int ln=31; int d10(int x) { int tmp[233]; for(int i=0;i<ln;i++) tmp[i]=div2(x,list[i]); int cur=tmp[0]; for(int i=1;i<ln;i++) cur=add(cur,tmp[i]); return cur; }
那个ln参数是人工调出来的...
并没有看懂这个点的题解啊QAQ
第九个点
排序?我们写一个冒泡排序!
接下来我们考虑如何求出min(a,b)...
其实只要a+min(b-a,0)即可!
那么我们就可以这样求出a和b两个数的较小值,从而将a和b放好位置(因为和不变)
所以我们写一个冒泡排序就可以了。min0参见第四个点。
int min0(int r) { cout.setf(ios::fixed); cout.precision(30); int x=addv(r,1e-30); int p=gp(x); int py=mul2(p,151); int s=gs(add(div2(x,150),py)); int bf=addv(fu(s),0.5); int m=mul2(bf,152); return fu(add(m,py)); } int aid[23]; void relax(int a,int b) { int s=add(aid[a],aid[b]); aid[a]=add(aid[a],min0(add(fu(aid[a]),aid[b]))); aid[b]=add(s,fu(aid[a])); } int main() { freopen("nodes9.out","w",stdout); for(int i=1;i<=16;i++) aid[i]=input(); for(int i=1;i<=16;i++) { for(int j=i+1;j<=16;j++) relax(i,j); } for(int i=1;i<=16;i++) out(aid[i]); }
最后一个点太难写啦!看心情可能会再更
成功得到85分~