[扩欧]JZOJ 5855 吃蛋糕

Description

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

Input

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

Output

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

Sample Input

样例输入 1
3
2 3 4
3 4 24
3 7 11
 
样例输入 2
4
12 13 1003
56 44 792
4616 5364 836482148
3836501 7035978 77151863500136
 

Sample Output

样例输出 1
13
0
 
样例输出 2
6
2
135
3
 
 

Data Constraint

对于 30%的数据 t<=10,a,b,c<=100
对于 60%的数据 t<=100,a,b,c<=10^9
对于 100%的数据 t<=10000,a,b,c<=10^14

分析

首先对于ax+by=c我们可以用扩欧来做

如果要求最小解,y=y/(lcm(a,b)/b)

然后取模则为y=(c-a*x)/b

然后一波快速乘优化就行

 

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;

ll Exgcd(ll a,ll b,ll &x,ll &y) {
    if (!b) {
        x=1;y=0;
        return a;
    }
    ll gcd=Exgcd(b,a%b,y,x);
    y-=a/b*x;
    return gcd;
}

ll Solve(ll a,ll b,ll c) {
    ll x,y,gcd=Exgcd(a,b,x,y);
    if (c%gcd) return 0;
    ll q=b/gcd;
    x=(c/gcd%q*x%q+q)%q;y=(c-a*x)/b;
    return y<0?0:y/(a/gcd)+1;
}

int main() {
    freopen("cake.in","r",stdin);
    freopen("cake.out","w",stdout);
    int t;
    scanf("%d",&t);
    while (t--) {
        ll a,b,c;
        scanf("%lld%lld%lld",&a,&b,&c);
        printf("%lld\n",Solve(a,b,c));
    }
    fclose(stdin);fclose(stdout);
}
View Code

 

posted @ 2018-09-13 20:27  Vagari  阅读(235)  评论(0编辑  收藏  举报