1352 集合计数 扩展欧几里德算法
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
既然选择了远方,就要风雨兼程~
posted on 2017-02-07 22:16 stupid_one 阅读(221) 评论(0) 编辑 收藏 举报