C. The Football Season
theme:给定n,p,w,d;求出一组x,y,z使得w*x+d*y=p,x+y+z=n,且x,y,z为自然数。1≤n≤10^12,0≤p≤10^17,1≤d<w≤10^5
solution:首先可看出这题就是求整数解x,y使得w*x+d*y=p,且x+y<=n,一个方程解两个未知数,枚举。但n很大,p也大,注意到x最大只能取min(n,p/w);而这题d,w比较小,所以可以从d,w范围下手看能不能缩小枚举范围。当枚举x的时候,y=(p-wx)/d=p/d-wx/d;要求y为整数,而若p/d-wx/d为或不为整数,则将x=x-d代入得p/d-wx/d+w,加的w并不影响是否为整数,可以看出每d个循环枚举x要么能得到一组整数解输出,要么就说明不存在整数解。所以只要枚举d个即可o(1e5)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
#define far(i,t,n) for(int i=t;i<n;++i)
#define pk(a) push_back(a)
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int inf=0x3f3f3f3f;
int mod=998244353;
int main()
{
ll n,p,w,d;
cin>>n>>p>>w>>d;
ll maxx=p/w;
ll minx=max(0LL,maxx-d);
int flag=0;
for(ll i=maxx;i>=minx;--i)
{
if(((p-i*w)%d==0)&&((i+(p-i*w)/d)<=n))
{
ll y=(p-i*w)/d;
flag=1;
cout<<i<<" "<<y<<" "<<n-i-y<<endl;
break;
}
}
if(!flag)
puts("-1");
return 0;
}