整理的算法模板:ACM算法模板总结(分类详细版)
链接:https://ac.nowcoder.com/acm/contest/4853/D
来源:牛客网
题目描述
算术能力是每个炉石玩家必不可少的,假设现在有三种伤害卡,伤害值分别是a,b,ca,b,ca,b,c。并且每种伤害卡的数量你可以认为是无限的。现在牛牛想知道是否存在一种方式可以刚好造成kkk点伤害,输出x,y,zx,y,zx,y,z分别表示三种伤害卡的使用个数。
数据保证一定存在解。如果存在多组解,输出任意一组。
输入描述:
一行四个整数分别表示a,b,c,ka,b,c,ka,b,c,k.
输出描述:
一行输出三个整数分别表示x,y,zx,y,zx,y,z.
示例1
输入
3 4 5 20
输出
4 2 0
.
- 题意:求ax+by+cz=k的任意一组非负整数解。
- 思路:用扩展欧几里得解方程;枚举1~k/a里面的所有数res,对于每一个数都对应一个方程by+cz=k-res;然后用扩展欧几里得解这个方程即可;注意解的过程中,对于解出来的第一个值y,要把它变成整数,利用y=y0+c/gcd(b,c)*t,也就是y=(y%g+g)%g;
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// 求x, y,使得ax + by = gcd(a, b)
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (!b)
{
x = 1; y = 0;
return a;
}
ll d = exgcd(b, a % b, y, x);
y -= (a/b) * x;
return d;
}
int main()
{
ll a,b,c,k;
cin >>a>>b>>c>>k;
ll g=__gcd(b,c);
for(int i=0;i<=k/a;i++)
{
if((k-a*i)%g!=0) continue;
ll x,y;
exgcd(b,c,x,y);
ll cnt=(k-a*i)/g;
x=x*cnt,y=y*cnt;
ll mod=c/g;
x=(x%mod+mod)%mod;
y=(k-a*i-b*x)/c;
if(x<=0||y<=0) continue;
cout <<i<<" "<<x<<" "<<y<<endl;
break;
}
}