zoukankan      html  css  js  c++  java
  • 旷野大计算

    image

    image

    这垃圾语言连个不扣分的乘法都没有...

    image

    任务怎么这么鬼畜啊...一个一个点来

    第一个点

    -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<<"
    ", ++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):

    image

    奥妙重重啊

    稍加考虑,我们可以发现...不用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);
    }

    第六个点

    又是进制转换,把十进制转回二进制?

    image

    好主意!

    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的异或值就行了。

    我构不出来...但是出题人构出来了...

    image

    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分~

  • 相关阅读:
    python 连接操作mysql数据库
    (转)postfix疯狂外发垃圾邮件之分析与解决
    ansible 常用方法
    用python2.7.9 写个小程序搜索某个目录下行有某关键字
    python获取文件扩展名的方法(转)
    ceph 池管理
    UVALive 5412 Street Directions
    UVALive 3231 Fair Share
    UVA 11478 Halum
    2015 Multi-University Training Contest 4 hdu 5338 ZZX and Permutations
  • 原文地址:https://www.cnblogs.com/zzqsblog/p/5715551.html
Copyright © 2011-2022 走看看