题解:CF1993F1 Dyn-scripted Robot (Easy Version)
题意
在平面直角坐标系中,机器人初始位于 ,有一段长度为 的仅包含 的操作序列 ,机器人将把此操作序列执行 轮,要求机器人任意时刻的位置都必须在 的矩形中,若按第 个操作移动会超出矩形,那么若 为 ,将 中所有 变成 ,所有 变成 ;若 为 也同理。变换后再执行第 个操作,注意变换对操作序列的影响会保留到下一轮。
求机器人在移动过程中经过 的次数(不包括初始状态)。
数据范围: 为数据组数,。
由于神秘原因,本题解的 对应原题中的 。
分析
场上想不出 F1 的简单做法,但会了 F2,然而由于时间原因最终没有调出来。
先考虑一个简单的转化:带限制走到 相当于不带限制走到 。
简单证明一下,假设一次 时超出了矩阵,那么 不受影响,若不改变操作序列,则相当于把走到 改为了走到 ; 也以此类推,所以转化成立。
于是问题要求经过 的次数,显然一轮后的位移是固定的,令其为 ,所以我们枚举一轮中第 个操作作为结尾,设第一轮中第 次操作后位于 ,那么在第 轮中机器人位于 。
先将 分开考虑,那么 。
可以转化为同余方程 ,用两次 分别算出两个方程的通解,再用一次 合并即可。
时间复杂度 。
代码
#include<bits/stdc++.h>
#define ll long long
#define PY puts("YES")
#define PN puts("NO")
using namespace std;
long long read(){
long long x=0,f=1;char ch=getchar();
while(!isdigit(ch))
{if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
void write(long long x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int N=1e6+10;
int t,n,h,w;
ll k,ans;
string s;
int fx[4]={0,0,-1,1};
int fy[4]={-1,1,0,0};
struct Node{
int x,y;
}a[N];
Node forward(Node p,int t){
return (Node){p.x+fx[t],p.y+fy[t]};
}
int turn(char c){
if(c=='D')return 0;
if(c=='U')return 1;
if(c=='L')return 2;
return 3;
}
long long exgcd(long long a,long long b,long long &x,long long &y){
if(!b){
x=1;y=0;
return a;
}
long long d=exgcd(b,a%b,x,y);
long long z=x;x=y;y=z-y*(a/b);
return d;
}
ll solve(Node p,ll k){
int vv=(p.x==0&&p.y==0);
p.x=h-p.x;p.y=w-p.y;
ll hx0,hy0,hd,hB;
hd=exgcd(a[n].x,h,hx0,hy0);
if(p.x%hd)return vv;
hB=h/hd;
hx0*=p.x/hd;hx0=(hx0%hB+hB)%hB;
ll wx0,wy0,wd,wB;
wd=exgcd(a[n].y,w,wx0,wy0);
if(p.y%wd)return vv;
wB=w/wd;
wx0*=p.y/wd;wx0=(wx0%wB+wB)%wB;
ll x0,y0,d,B,xy;
if(wx0<hx0)swap(wx0,hx0),swap(hB,wB);
xy=(wx0-hx0)%wB;
d=exgcd(hB,wB,x0,y0);
if(xy%d)return vv;
B=wB/d;
x0*=xy/d;x0=(x0%B+B)%B;
ll u=k-hx0;if(u<0)return vv;
u=(u/hB-x0);if(u<0)return vv;
u/=B;
return u+vv+(x0*hB+hx0!=0&&x0*hB+hx0<=k);
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
t=read();
while(t--){
cin>>n>>k>>h>>w>>s;
a[0]=(Node){0,0};
h*=2;w*=2;
for(int i=1;i<=n;i++){
a[i]=forward(a[i-1],turn(s[i-1]));
a[i].x=(a[i].x%h+h)%h;
a[i].y=(a[i].y%w+w)%w;
}
ans=0;
for(int i=1;i<=n;i++)
ans+=solve(a[i],k-1);
cout<<ans<<endl;
}
return 0;
}
本文作者:luckydrawbox
本文链接:https://www.cnblogs.com/luckydrawbox/p/18526430
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步