【题目】
题目描述:
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(x0−k∗b)+b(y0+k∗a)=c,我们就可以通过这个调整根
先求出一组特解,把 x x x 调到非负情况下最小(即此时 x ≥ 0 x ≥ 0 x≥0 且 x − b < 0 x-b<0 x−b<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;
}