【WOJ 4078】吃蛋糕

【题目】

题目描述:

Beny 想要用蛋糕填饱肚子。Beny 一共想吃体积为 c c c 的蛋糕,他发现有两种蛋糕可以吃,一 种体积为 a a a,一种体积为 b b b,但两种蛋糕各有特色。Beny 想知道他一共有多少种不同吃法, 使得他恰好可以填饱肚子。

输入格式:

第一行一个 t t t

接下来 t t t 行,每行三个正整数 a , b , c a,b,c a,b,c

输出格式:

对于每个 a , b , c a,b,c a,b,c,输出一个整数表示有几种不同吃法

样例数据:

【样例1】

输入
3
2 3 4
3 4 24
3 7 11

输出
1
3
0

【样例2】

输入
4
12 13 1003
56 44 792
4616 5364 836482148
3836501 7035978 77151863500136

输出
6
2
135
3

备注:

【数据范围】
对于 30 % 30\% 30% 的数据 t t t ≤ 10 , , a,b,c$ ≤ 100 100 100
对于 60 % 60\% 60% 的数据 t t t 100 100 100 a , b , c a,b,c a,b,c 1 0 9 10^9 109
对于 100 % 100\% 100% 的数据 t t t 10000 10000 10000 a , b , c a,b,c a,b,c 1 0 14 10^{14} 1014

【分析】

题解:扩展欧几里得算法

这道题数据有锅。。。全机房都卡在 90 90 90 分,不过题目本身还是不错

题目的意思就是求出 a x + b y = c ax+by=c ax+by=c 有多少组非负整数解

若我们求出一组特解 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),那么有 a ( x 0 − k ∗ b ) + b ( y 0 + k ∗ a ) = c a(x_0-k*b)+b(y_0+k*a)=c a(x0kb)+b(y0+ka)=c,我们就可以通过这个调整根

先求出一组特解,把 x x x 调到非负情况下最小(即此时 x ≥ 0 x ≥ 0 x0 x − b &lt; 0 x-b&lt;0 xb<0),并在 x x x 最小的情况下确定 y y y 的值,然后相当于是求 y y y 在大于等于 0 0 0 的情况下能减多少个 a a a(就是 y / a + 1 y/a+1 y/a+1

不要在意奇怪的快速乘

【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll Multiply(ll a,ll b,ll c)
{
	ll res=a;
	int ans=0;
	while(b)
	{
		if(b&1)
		  ans=(ans+res)%c;
		res=(res+res)%c;
		b>>=1;
	}
	return ans;
}
void exgcd(ll a,ll b,ll &x,ll &y)
{
	if(!b)
	{
		x=1,y=0;
		return;
	}
	exgcd(b,a%b,y,x);
	y-=a/b*x;
}
ll solve(ll a,ll b,ll c)
{
	ll gcd=__gcd(a,b);
	if(c%gcd)  return 0;
	ll x,y;exgcd(a,b,x,y);
	a/=gcd,b/=gcd,c/=gcd;
	x=(Multiply(x,c%b,b)+b)%b;
	y=(c-a*x)/b;
	if(y<0)  return 0;
	return y/a+1;
}
int main()
{
	int t;
	long long a,b,c;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%lld%lld%lld",&a,&b,&c);
		printf("%lld\n",solve(a,b,c));
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值