欧几里得(炒鸡有趣的思维题)(提升思维能力)(阅读点赞的rp++++++)
序
其实这道题,emm,怎么说呢
没有什么特别的知识点
只是我觉得还蛮有意思
就发上来给大家看看
题意
今有一数轴, S S S 处有一颗棋子,要执行 N N N 次操作,每次操作中:
- 若棋子位置 ≥ T \ge T ≥T ,向左移动 X X X
- 反之向右移动 Y Y Y
问 n n n 次操作后,棋子的位置。
( T T T 组数据)
T ≤ 1 0 3 , N ≤ 1 0 18 , X , Y , ∣ S ∣ , ∣ T ∣ ≤ 1 0 18 T \le 10^3,N \le 10^{18},X,Y,|S|,|T| \le 10^{18} T≤103,N≤1018,X,Y,∣S∣,∣T∣≤1018
解法
首先,如果棋子只用往一边移动,那么直接特判输出
思考一下易得,如果有改变过方向,那么最后的落点一定在 [ t − x , t + y ) [t-x,t+y) [t−x,t+y) 这段区间内1
处理一下,先把单个方向走的那部分搞定,这时候的 $ s $ 就在这个区间内,我们就可以进行操作啦
我们设往左走 a a a 步,那么往右走 n − a n-a n−a 步~~(废话,不然呢)~~
(不要怕未知数 a a a ,等会会化掉的)
那么最终的位置就是 s − a x + ( n − a ) y s-ax+(n-a)y s−ax+(n−a)y ,化简一下得到 s − a ( x + y ) + n y s-a(x+y)+ny s−a(x+y)+ny
看回 [ t − x , t + y ) [t-x,t+y) [t−x,t+y) 的区间,一共有 x + y x+y x+y 个元素
那么我们就把最终位置 % ( x + y ) \%(x+y) %(x+y) ,这样得到的数都是唯一的
a ( x + y ) % ( x + y ) = 0 a(x+y)\%(x+y)=0 a(x+y)%(x+y)=0
就可以化简成 ( s + n y ) % ( x + y ) (s+ny)\%(x+y) (s+ny)%(x+y)
再求出最左边(即 ( t − x ) % ( x + y ) (t-x)\%(x+y) (t−x)%(x+y) 的值,就珂以以此为基准求出最终位置啦
Q:怎么求?
A:其实要分两种情况:(我们设 ( s + n y ) % ( x + y ) (s+ny)\%(x+y) (s+ny)%(x+y) 的值为 p p p , ( t − x ) % ( x + y ) = q (t-x)\%(x+y)=q (t−x)%(x+y)=q ,假设 x + y = 5 , p = 3 x+y=5,p=3 x+y=5,p=3)
-
q ≤ p q \le p q≤p ,例(取模后 [ t − x , x + y ) [t-x,x+y) [t−x,x+y) 的值):
1 , 2 , 3 , 4 , 0 1,2,3,4,0 1,2,3,4,0
那么此时的 q = 1 q=1 q=1 ,答案即为 ( t − x ) + ( p − q ) (t-x)+(p-q) (t−x)+(p−q)
-
q > p q>p q>p ,例:
4 , 0 , 1 , 2 , 3 4,0,1,2,3 4,0,1,2,3
此时 q = 1 q=1 q=1 ,那就不能直接减了,要把 q q q 加上模数 x + y x+y x+y ,所以答案为 $ (t-x)+(x+y)+(p-q)=(t+y)+(p-q)$
自我感觉代码蛮易懂的,还有不理解的可以再仔细看下(关键几行有注释)
而且很短诶!!!
删掉快读快输就那么一丁点
代码
#include<cstdio>
#define ll8 __int128
using namespace std;
ll8 rd()
{
ll8 s1=0,s2=1;
char t=getchar();
while((t<'0')||(t>'9'))
{
t=getchar();
if(t=='-')
{
s2=-1;
}
}
while((t>='0')&&(t<='9'))
{
s1=(s1*10)+t-'0';
t=getchar();
}
return s1*s2;
}
void wrt(ll8 x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
wrt(x/10);
}
putchar(x%10+'0');
}
ll8 slv()
{
ll8 n=rd(),s=rd(),t=rd(),x=rd(),y=rd();
if((s-(n*x))>=t)
{
return s-(n*x);
}
if((s+(n*y))<=t)
{
return s+(n*y);
}//特判掉不用转弯的情况
if(s<(t-x))
{
ll8 tt=(t-s+y-1)/y;
s+=tt*y;
n-=tt;
}
if(s>=(t+y))
{
ll8 tt=(s-t+x-1)/x;
s-=tt*x;
n-=tt;
}//处理掉单个方向走的部分
ll8 p=(s+(n*y))%(x+y),q=(t+y)%(x+y);
if(p>=q)
{
return t-x+p-q;
}
else
{
return t+y+p-q;
}//分两种情况讨论
}
int main()
{
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
wrt(slv());
putchar('\n');
}
return 0;
}
PS:本题要使用 __int128
,不会用的读者可以借机了解下。
__int128
可以进行 +,-,*,/,%
五种运算,但是输入输出要用类似快读快输的方法。
后记
怎么样?是不是很好玩?
作者诚不欺你对吧?
那就点个赞吧
关注+收藏哦
谢谢🌷(今天送朵不一样的花)
[ x , y ] [x,y] [x,y] 意为 x ∼ y x \sim y x∼y 的区间,包括 x , y x,y x,y ; ( x , y ) (x,y) (x,y) 意为不包括 x , y x,y x,y ↩︎