kkio。|

_kkio

园龄:1年7个月粉丝:6关注:1

我们有相遇的时间(time)

终于还是写到这个了。。。

题意:

一个平面直角坐标系上,给你六个点,分别是 (0,0),(0,1),(1,0),(1,1),(0,0.5),(1,0.5)。你随时可以做两种操作,第一种是选两个点的编号,在这两个点之间得到一条直线,这条直线的编号为上个直线编号加一,第二种选两条有交直线,并得到交点,交点编号为上个点编号加一。

现在给你四个参数 0<Xa<Xb<1e9,0<Ya<Yb<1e9,构造一种操作方案得到点 (XaXb,YaYb)。使操作一总次数不超过 270 次。

解法

考虑如何得到坐标轴上的任意一点,再做过这个点的平行坐标的线,求交就好了。XY 轴本质一样,现在考虑 Y 轴上一点。一个很好的想法是这样:

1

上下两条线的情况本质是对称的,只需要得到两条线上的任意一点即可。

考虑倍增。每次将长度乘二或乘二加一。

实现方式是找到四个点 (0,13),(13,13),(1,53),(53,53),发现如果以 (0,0)(1,1) 为基准点,当点在 y=1 上时,d 为它到 (1,1) 距离,当在 y=0 上时为到 (0,0) 的距离,那么以 (0,0) 为起始点,d 初始为 0。若是当前点和 (0,13)(1,53) 作直线交 y=0y=1 于另一个点时,这个点的 d 会乘二并加一,如果是另外两个点的话就只会乘二。

如图,点 Bd1,连出两条直线于 y=1 交点的 d 分别是 32

以此就可以倍增了。剩下的两件事,一是得到那四个点,而是作一条过任意点并平行于坐标轴的直线,这是初中直尺作图简单的,应该有一万种做法。

#include <bits/stdc++.h>
using namespace std;
int pid,lid;
struct opt{int type,a,b;};
vector<opt> Ans; 
inline int getl(int A,int B)
{Ans.push_back({1,A,B});++lid;return lid;}
inline int getp(int la,int lb)
{Ans.push_back({0,la,lb});++pid;return pid;}
struct solver{
    int A,B,C,D,M1,M2,I,E,F,G,H;
    int lf,lg;
    inline void beready()
    {
        lf=getl(A,B);lg=getl(C,D);
        int tl=getl(C,A),tr=getl(D,B);
        int tp=getl(B,M1),tq=getl(D,M2);
        F=getp(tl,tp),H=getp(tl,tq);
        tl=getl(C,M1),tr=getl(A,M2);
        int tmp1=getp(lf,tl),tmp2=getp(lg,tr);
        int cr=getl(tmp1,tmp2);
        E=getp(cr,getl(A,D)),G=getp(cr,getl(C,B));
    }
    int calc(int X,int opt)
    {
        int d=0;
        int nwp=((opt==0)?A:C);
        for(int i=30;i>=0;i--)
        {
            if(X&(1<<i))
            {
                if(((i&1)^opt)==0){nwp=getp(getl(nwp,E),lg);}
                else {nwp=getp(getl(nwp,G),lf);}
                d=d<<1|1;
            }
            else 
            {
                if(((i&1)^opt)==0){nwp=getp(getl(nwp,F),lg);}
                else {nwp=getp(getl(nwp,H),lf);}
                d=d<<1;
            }
        }
        return nwp;
    }
    inline int getP(int Ya,int Yb)
    {
        if(Ya==1&&Yb==2)return getl(M1,M2);
        int upP=calc(Yb-Ya+1,0);
        int dwP=calc(Ya,1);
        int RP=getp(getl(upP,dwP),getl(A,D));
        int RG=getp(getl(RP,I),getl(C,B));
        int tk=getp(lg,getl(A,M2));int tl=getp(lf,getl(D,M2));
        int EI=getp(getl(tk,B),getl(tl,C));
        return getl(RP,getp(getl(tk,tl),getl(RG,EI)));
    }
}SX,SY;
int Xa,Xb,Ya,Yb;
int A,B,C,D,M1,M2,M3,M4,I,ans=1;
int main()
{
//	freopen("ex_time1.in","r",stdin);
//	freopen("time.out","w",stdout); 
    scanf("%d%d%d%d",&Xa,&Xb,&Ya,&Yb);
    int g1=__gcd(Xa,Xb),g2=__gcd(Ya,Yb);
    Xa/=g1,Xb/=g1,Ya/=g2,Yb/=g2;
    pid=6;A=1,M1=2,D=3,B=4,M2=5,C=6;
    I=getp(getl(A,C),getl(B,D));
	M3=getp(getl(C,D),getl(getp(getl(getp(getl(C,M1),getl(B,A)),D),getl(B,C)),A));
    M4=getp(getl(M3,I),getl(A,B));
    SX.A=A,SX.B=B,SX.C=C,SX.D=D,SX.M1=M1,SX.M2=M2,SX.I=I;
    SY.A=A,SY.B=D,SY.C=C,SY.D=B,SY.M1=M4,SY.M2=M3,SY.I=I;
    SX.beready();SY.beready();
    int TY=SX.getP(Ya,Yb);
    int TX=SY.getP(Xa,Xb);
    ans=getp(TX,TY);
    printf("%d\n",Ans.size()+1);
    for(auto v:Ans)printf("%d %d %d\n",v.type,v.a,v.b);
    printf("2 %d\n",ans);
    return 0;
}

本文作者:_kkio

本文链接:https://www.cnblogs.com/hikkio/p/17607255.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   _kkio  阅读(13)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起