[CF538G] Berserk Robot

链接

题意

有个小机器人在 \((0,0)\),构造一个长度为 \(m\) 的程序,每次执行 \(LRDU\) 中的一个,使得循环执行这个程序,在 \(t_i\) 时间在点 \((x_i,y_i)\),\(t_i\leq 10^{18}\)。

题解

考虑每次钦定多走了 \((1,0)\),然后旋转坐标轴。

[CF538G] Berserk Robot

这样两维就可以分开做了。

设 \(T\) 表示的是完整运行一个周期之后的坐标,设 \(k_i=\lfloor\frac{x_i}{m}\rfloor,w_i=x_i\bmod{m}\),令 \(s_i\) 表示 \(i\) 时刻的位置,有 \(k_i=s_{w_i}+Tk_i\)。

显然 \(|s_{i}-s_{j}|\leq |j-i|\),然后可以确定出 \(T\) 的范围,显然最后结果是一个区间,随意取一个即可。

然后反推出 \(s\) 即可。复杂度 \(O(n\log n)\)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 2000010
#define ll long long
#define ld long double
using namespace std;
struct node{
    ll x,k,w;
    node(ll X=0,ll K=0,ll W=0):x(X),k(K),w(W){}
    bool operator <(const node a)const{return w<a.w;}
}x[N],y[N];
int n,m;
void solve(node a[],int ans[])
{
    a[n+1]=node(0,-1,m);
    ll l=0,r=m;
    for(int i=1;i<=n+1;i++)
    {
        ll x=a[i].x-a[i-1].x,w=a[i-1].w-a[i].w;
        ld k=a[i].k-a[i-1].k;
        if(k<0) l=max(l,(ll)ceil(x/k)),r=min(r,(ll)floor((x+w)/k));
        else if(k>0) l=max(l,(ll)ceil((x+w)/k)),r=min(r,(ll)floor(x/k));
        else if(x+w>0 || x<0){puts("NO");exit(0);}
    }
    if(l>r){puts("NO");exit(0);}
    ll s=l;int c=0;
    for(int i=1;i<=n+1;i++)
    {
        ll x=a[i].x-a[i-1].x-(a[i].k-a[i-1].k)*s;
        int t=a[i].w-a[i-1].w;
        while(t --> 0) ans[++c]=(x --> 0);
    }
}
int ax[N],ay[N];
const char ans[]="DLRU";
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        ll t,x,y;
        scanf("%lld%lld%lld",&t,&x,&y);
        if((t+x+y)&1){puts("NO");return 0;}
        ::x[i]=node((x+y+t)>>1,t/m,t%m);
        ::y[i]=node((-x+y+t)>>1,t/m,t%m);
    }
    sort(x+1,x+n+1);sort(y+1,y+n+1);
    solve(x,ax);solve(y,ay);
    for(int i=1;i<=m;i++) putchar(ans[ax[i]<<1|ay[i]]);
    return 0;
}
上一篇:robot脚本中使用python文件中定义的变量


下一篇:UI自动化测试中的坑