Jumping Joe SGU - 141
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
题意: 给定 x1,x2,p,k 让你求满足 (p1-n1)*x1+(p2-n2)*x2=p&& p1+n1+p2+n2=k 的 任意一组解
思路: 考虑第一个式子 (p1-n1)*x1+(p2-n2)*x2=p ,可以用 扩欧求出 (p1-n1) (p2-n2) 的通解,
并且可以得出 满足方程的 最小 T= abs(p1-n1) +abs(p2-a2)
对于<k的情况考虑剩下的 last =(k-T) 的奇偶性,显然对于偶数情况可以直接凑出一组解,
那么对于奇数情况, 此时就需要考虑如何变为偶数情况了,考虑扩欧的通解形式,只有当
abs(x2/d-x1/d) 为 奇数的时候才可以,显然偶数不行,
对于奇数的情况需要找到 较小的一种情况, 继续考虑是否大于 k ,然后求解。
#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include <bits/stdc++.h>
#include<string>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<algorithm>
#define maxn 10010
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MOD 1000000007
#define ll long long
using namespace std;
ll ex_gcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
int main()
{
ll x1,x2,p,k;
scanf("%lld%lld%lld%lld",&x1,&x2,&p,&k);
{
ll x,y,d;
d=ex_gcd(x1,x2,x,y);
if(p%d)
{
puts("NO");
return 0;
}
x*=p/d;
y*=p/d;
ll g1=x2/d;
ll g2=x1/d;
while(abs(x+g1)+abs(y-g2)<abs(x)+abs(y)) x+=g1,y-=g2;
while(abs(x-g1)+abs(y+g2)<abs(x)+abs(y)) x-=g1,y+=g2;
if(abs(x)+abs(y)>k)
{
puts("NO");
return 0;
}
ll last=k-abs(x)-abs(y);
ll p1,p2,n1,n2;
p1=p2=n1=n2=0;
if(last%2==0)
{
if(x<0) p1=0,n1=-x;
else n1=0,p1=x;
if(y<0) p2=0,n2=-y;
else n2=0,p2=y;
p1+=last/2;
n1+=last/2;
}
else
{
if(abs(g1-g2)%2==0)
{
puts("NO");
return 0;
}
if(abs(x+g1)+abs(y-g2)<abs(x-g1)+abs(y+g2)) x+=g1,y-=g2;
else x-=g1,y+=g2;
if(abs(x)+abs(y)>k)
{
puts("NO");
return 0;
}
ll last=k-abs(x)-abs(y);
if(x<0) p1=0, n1=-x;
else p1=x,n1=0;
if(y<0) p2=0, n2=-y;
else p2=y,n2=0;
p1+=last/2;
n1+=last/2;
}
printf("YES\n%lld %lld %lld %lld\n",p1,n1,p2,n2);
}
return 0;
}