牛客练习赛60 D— 斩杀线计算大师

整理的算法模板: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;
	}
}
发布了224 篇原创文章 · 获赞 56 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/weixin_43872728/article/details/105152825