【题目】
题目描述:
Beny 想要用蛋糕填饱肚子。Beny 一共想吃体积为 ccc 的蛋糕,他发现有两种蛋糕可以吃,一 种体积为 aaa,一种体积为 bbb,但两种蛋糕各有特色。Beny 想知道他一共有多少种不同吃法, 使得他恰好可以填饱肚子。
输入格式:
第一行一个 ttt
接下来 ttt 行,每行三个正整数 a,b,ca,b,ca,b,c
输出格式:
对于每个 a,b,ca,b,ca,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% 的数据 ttt ≤ 10,,,a,b,c$ ≤ 100100100
对于 60%60\%60% 的数据 ttt ≤ 100100100,a,b,ca,b,ca,b,c ≤ 10910^9109
对于 100%100\%100% 的数据 ttt ≤ 100001000010000,a,b,ca,b,ca,b,c ≤ 101410^{14}1014
【分析】
题解:扩展欧几里得算法
这道题数据有锅。。。全机房都卡在 909090 分,不过题目本身还是不错
题目的意思就是求出 ax+by=cax+by=cax+by=c 有多少组非负整数解
若我们求出一组特解 (x0,y0)(x_0,y_0)(x0,y0),那么有 a(x0−k∗b)+b(y0+k∗a)=ca(x_0-k*b)+b(y_0+k*a)=ca(x0−k∗b)+b(y0+k∗a)=c,我们就可以通过这个调整根
先求出一组特解,把 xxx 调到非负情况下最小(即此时 x≥0x ≥ 0x≥0 且 x−b<0x-b<0x−b<0),并在 xxx 最小的情况下确定 yyy 的值,然后相当于是求 yyy 在大于等于 000 的情况下能减多少个 aaa(就是 y/a+1y/a+1y/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;
}