SGU 141.Jumping Joe 数论,拓展欧几里得,二元不等式 难度:3
2014-10-31 09:42
302 查看
141. Jumping Joe
time limit per test: 0.25 sec.
memory limit per test: 4096 KB
Joe is a frog who likes to jump a lot. In fact, that's all he does: he jumps forwards and backwards on the integer axis (a straight line on which all the integer numbers, both positive and negative are marked). At first, Joe sits next to the point marked with 0. From here, he can jump in the positive or the negative direction a distance equal to either x1 or x2. From the point where he arrived, he can jump again a distance equal to x1 or x2, in the positive or the negative direction and so on.. Joe wants to arrive next to the point marked with the number P, after exactly K jumps. You have to decide whether such a thing is possible.
Input
The input will contain four integers: x1, x2 (0 < x1 , x2 < 40 000), P (-40 000 < P < 40 000) and K (0 <= K < 2 000 000 000), separated by blanks.
Output
The first line of output will contain the word "YES", in case Joe can reach the point marked with P after exactly K jumps, or "NO", otherwise. In case the answer is "YES", the next line should contain four integers, separated by blanks: P1 , N1 , P2 and N2. P1 is the number of times Joe jumped in the positive direction a distance equal to x1. N1 is the number of times Joe jumped in the negative direction a distance equal to x1. P2 is the number of times Joe jumped in the positive direction a distance equal to x2. N2 is the number of times Joe jumped in the negative direction a distance equal to x2. In other words, you should find four non-negative integers, so that:
P1*x1 - N1*x1 + P2*x2 - N2*x2 = P
P1 + N1 + P2 + N2 = K
In case there are more quadruples (P1,N1,P2,N2) which are solutions for the problem, you may print any of them.
Sample Input
Sample Output
time limit per test: 0.25 sec.
memory limit per test: 4096 KB
Joe is a frog who likes to jump a lot. In fact, that's all he does: he jumps forwards and backwards on the integer axis (a straight line on which all the integer numbers, both positive and negative are marked). At first, Joe sits next to the point marked with 0. From here, he can jump in the positive or the negative direction a distance equal to either x1 or x2. From the point where he arrived, he can jump again a distance equal to x1 or x2, in the positive or the negative direction and so on.. Joe wants to arrive next to the point marked with the number P, after exactly K jumps. You have to decide whether such a thing is possible.
Input
The input will contain four integers: x1, x2 (0 < x1 , x2 < 40 000), P (-40 000 < P < 40 000) and K (0 <= K < 2 000 000 000), separated by blanks.
Output
The first line of output will contain the word "YES", in case Joe can reach the point marked with P after exactly K jumps, or "NO", otherwise. In case the answer is "YES", the next line should contain four integers, separated by blanks: P1 , N1 , P2 and N2. P1 is the number of times Joe jumped in the positive direction a distance equal to x1. N1 is the number of times Joe jumped in the negative direction a distance equal to x1. P2 is the number of times Joe jumped in the positive direction a distance equal to x2. N2 is the number of times Joe jumped in the negative direction a distance equal to x2. In other words, you should find four non-negative integers, so that:
P1*x1 - N1*x1 + P2*x2 - N2*x2 = P
P1 + N1 + P2 + N2 = K
In case there are more quadruples (P1,N1,P2,N2) which are solutions for the problem, you may print any of them.
Sample Input
2 3 -1 12
Sample Output
YES 1 0 5 6 这题第一眼觉得是拓展欧几里得,设pn0=p0-n0,pn1=p1-n1,则可以通过拓展欧几里得得到一组满足等式1 的解,但是怎么得到四个答案数字都非负这一点卡了好久 明显,数据之间相差越小越优,且n0>=max(-pn0,0),n1>=abs(-pn1,0),p0>=max(pn0,0),p1>=abs(pn1,0) 则p0+p1+n0+n1=k>=(max(pn0,0)+max(-pn0,0)+max(pn1,0)+max(-pn1,0)),也就是说abs(pn1)+abs(pb0)<=k 又因为已经求出了一组pn1*x1+pn0*x0=pp,所以总有某个t使得(pn1-x0/gcd*t)*x1+(pn0-x1/gcd*t)*x0=pp 这里题解使用了暴力,从-40000求到40000 当确定一对pn0,pn1的时候,若从n0开始推起,那么n0=max(0,-pn0)(后面的是pn0为负数的时候p0为0,有问题的是第一次用pn0或pn1推出另一个数字的步骤,可能会导致负数,先确保这一步骤),n0+n1=(k-pn0-pn1)/2,可以解出这四个数字
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; ll extgcd(ll a,ll b,ll & x,ll &y){ if(b==0){ y=0; x=1; return a; } int t=extgcd(b,a%b,y,x); y-=a/b*x; return t; } ll x[2],p[2],n[2],pp,k,pn[2]; int main(){ scanf("%I64d%I64d%I64d%I64d",x+0,x+1,&pp,&k); ll gcd=extgcd(x[0],x[1],pn[0],pn[1]); if(pp%gcd!=0){puts("NO");return 0;} ll r=pp/gcd; pn[0]*=r;pn[1]*=r; ll t[2]; t[0]=x[1]/gcd;t[1]=x[0]/gcd; pn[0]-=40000*t[0];pn[1]+=40000*t[1]; ll temp[2],sum=abs(pn[0])+abs(pn[1]); for(int i=-40000;i<=40000;i++){ if((k+pn[0]+pn[1])%2==0&&(abs(pn[0])+abs(pn[1]))<sum){ sum=abs(pn[0])+abs(pn[1]); temp[0]=pn[0]; temp[1]=pn[1]; } pn[0]+=t[0];pn[1]-=t[1]; } pn[1]=temp[1];pn[0]=temp[0]; if(sum>k){puts("NO");return 0;} n[0]=max(0LL,-pn[0]); p[0]=pn[0]+n[0]; p[1]=(pn[0]+pn[1]+k)/2-p[0]; n[1]=p[1]-pn[1]; {printf("YES\n%I64d %I64d %I64d %I64d\n",p[0],n[0],p[1],n[1]);} return 0; }
相关文章推荐
- sgu106.The equation 拓展欧几里得 难度:0
- BZOJ-2242 计算器 快速幂+拓展欧几里得+BSGS(数论三合一)
- [zoj 3774]Power of Fibonacci 数论(二次剩余 拓展欧几里得 等比数列求和)
- 7C. Line【拓展欧几里得】 数论模板
- BZOJ-2242 计算器 快速幂+拓展欧几里得+BSGS(数论三合一)
- 数论及应用学习__Part1 拓展欧几里得【3/5】
- 数论基础(gcd + 拓展欧几里得)
- SGU 140. Integer Sequences 线性同余,数论 难度:2
- 模板 2018-01-27 数论 最大公因数 最小公倍数 拓展欧几里得 GCD LCM 逆元
- sgu 137. Funny Strings 线性同余,数论,构造 难度:3
- 数论之欧几里得与拓展欧几里得算法
- 【数论】拓展欧几里得
- 数论 + 扩展欧几里得 - SGU 106. The equation
- SGU 140 Integer Sequences(拓展欧几里得)
- SGU 106 The equation(拓展欧几里得)
- 数论之拓展欧几里得求解不定方程和同余方程组(一)
- ACM:数论专题——拓展欧几里得
- 数论 + 扩展欧几里得 - SGU 106. The equation
- (数论)整数二元一次不定方程(扩展欧几里得求解)
- 数论 拓展欧几里得定理