您的位置:首页 > 其它

1352 集合计数 扩展欧几里德算法

2017-02-07 22:16 204 查看
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1352

题目的本意就是要求

ax+by=n+1

a * x + b * y = c,在x >= 1和y >= 1的条件下的解的个数。

①、等于0的情况是:

1、方程无解,

2、最小的解就是(1. 1),大家都是1倍,如果比c还大,那就是0

3、设最小的解是x1,如果c - a * x1 < b,那也不行。也就是b不够一倍了。

其他的:(设x1是最小的正整数解)

通解就是x0 = x1 + b / (abgcd) * k,(k >= 0)

然后带入去a * x + b * y = c,同样c - a * x1也是要大于等于b才行,因为起码都要一倍。

然后解出的k,就是答案。包括上0,所以是k + 1

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
LL exgcd(LL a, LL mod, LL &x, LL &y) {
//求解a关于mod的逆元     ★:当且仅当a和mod互质才有用
if (mod == 0) {
x = 1;
y = 0;
return a;//保留基本功能,返回最大公约数
}
LL g = exgcd(mod, a % mod, x, y);
LL t = x;    //这里根据mod==0  return回来后,
x = y;  //x,y是最新的值x2,y2,改变一下,这样赋值就是为了x1=y2
y = t - (a / mod) * y;    // y1=x2(变成了t)-[a/mod]y2;
return g;            //保留基本功能,返回最大公约数
}

bool get_min_number (LL a, LL b, LL c, LL &x, LL &y) { //得到a*x+b*y=c的最小整数解
LL abGCD = __gcd(a, b);
if (c % abGCD != 0) return false; //不能整除GCD的话,此方程无解
a /= abGCD;
b /= abGCD;
c /= abGCD;
LL tx, ty;
exgcd(a, b, tx, ty); //先得到a*x+b*y=1的解,注意这个时候gcd(a,b)=1
x = tx * c;
y = ty * c;  //同时乘上c,c是约简了的。得到了一组a*x + b*y = c的解。
LL haveSignB = b;
if (b < 0) b = -b;     //避免mod负数啊,模负数没问题,模了负数后+负数就GG
x = (x % b + b) % b;  //最小解
if (x == 0) x = b; //避免x = 0不是"正"整数  不要用这个,溢出
y = (c - a * x); // haveSignB;
return true; //true代表可以
}

void work() {
LL a, b, c;
cin >> c >> a >> b;
c++;
if (c % __gcd(a, b) != 0 || a + b > c) {
cout << 0 << endl;
return;
}
LL x1, y1;
get_min_number(a, b, c, x1, y1);
LL t = c - b - a * x1;
if (c - x1 * a < b) {
//        cout << t << endl;
//        cout << c << " " << a << " " << b << endl;
//        while(1);
cout << 0 << endl;
return;
}
t /= a / __gcd(a, b) * b;
cout << t + 1 << endl;
}

int main() {
#ifdef local
freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
IOS;
int t;
cin >> t;
while (t--) work();
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: