上次做2017 apac test 最后一轮的时候,第三题需要使用扩展欧几里德算法来求解方程的解的个数,刚好学习一下这个算法。上次学了一下,忘记记录下来,这次在做hr的题目的时候,有需要这个算法,还是不熟练,这里还是把上次的代码,先贴出来吧,需要的进行研究!
1 #include<bits/stdc++.h> 2 #define pb push_back 3 #define FOR(i, n) for (int i = 0; i < (int)n; ++i) 4 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl 5 typedef long long ll; 6 using namespace std; 7 typedef pair<int, int> pii; 8 const int maxn = 1e3 + 10; 9 int a, b; 10 int gcd(int x, int y) { 11 if(y == 0) return x; 12 return gcd(y, x % y); 13 } 14 int gcd2(int x, int y) { 15 while(y != 0) { 16 int t = x % y; 17 x = y; 18 y = t; 19 } 20 return x; 21 } 22 int exgcd(int a, int b, int &x, int &y) { 23 if(b == 0) { 24 x = 1; 25 y = 0; 26 return a; 27 } 28 int r = exgcd(b, a % b, x, y); 29 int t = x; 30 x = y; 31 y = t - a / b * y; 32 return r; 33 } 34 int work(int a, int b, int c) { 35 int x, y; 36 ll t = exgcd(a, b, x, y); 37 //cout << t << " " << x << " " << y << endl; 38 if(c % t != 0) return 0; 39 ll f = c / t; 40 //double z1 = 1.0 * -x * f * t / b; 41 //double z2 = 1.0 * y * f * t / a; 42 //int x1 = z1, x2 = z2; 43 ll t1 = floor(1.0 * -x * f * t / b); 44 ll t2 = floor(1.0 * y * f * t / a); 45 //cerr << z1 << " " << x1 << " " << t1 << " " << z2 << " " << x2 << " " << t2 << endl; 46 if(1ll * y * f * t % a == 0) t2--; 47 return t2 - t1 < 0 ? 0 : t2 - t1; 48 } 49 /* 50 cin >> a >> b; 51 cout << __gcd(a, b) << endl; 52 cout << gcd(a, b) << " " << gcd2(a, b) << endl; 53 int x, y; 54 int t = exgcd(a, b, x, y); 55 cout << t << " " << x << " " << y << endl; 56 */ 57 void extgcd(ll a,ll b,ll& d,ll& x,ll& y){ 58 if(!b){ 59 d=a;x=1;y=0; 60 }else{ 61 extgcd(b,a%b,d,y,x); 62 y-=x*(a/b); 63 } 64 } 65 66 int work1(int a,int b,int n){ 67 if(n%__gcd(a,b)!=0)return 0; 68 ll g,p0,q0; 69 extgcd(a,b,g,p0,q0); 70 p0*=n/g;q0*=n/g; 71 int less=floor((-p0)*g*1.0/b),great=floor(q0*g*1.0/a); 72 if(q0*g%a==0)--great; 73 return great-less<0?0:great-less; 74 } 75 void solve1() { 76 cin >> a >> b; 77 ll res = 0; 78 //if(a % b == 0) res++; 79 for (int i = b; i <= a; i += b) { 80 int now = a; 81 if(now % i == 0) res++; 82 res += work(i, i + 1, now); 83 res += work(i, i + 2, now); 84 for (int j = 1; ; j++) { 85 int t = now - i * j; 86 if(t <= 0) break; 87 res += work(i + 1, i + 2, t); 88 } 89 //cout << i << " " << res << endl; 90 } 91 cout << res << endl; 92 } 93 ll work2(int a, int b, int c) { 94 int x, y; 95 ll t = exgcd(a, b, x, y); 96 //cout << t << " " << x << " " << y << endl; 97 if(c % t != 0) return 0; 98 ll f = c / t; 99 //double z1 = 1.0 * -x * f * t / b; 100 //double z2 = 1.0 * y * f * t / a; 101 //int x1 = z1, x2 = z2; 102 ll t1 = floor(1.0 * -x * f * t / b); 103 ll t2 = floor(1.0 * y * f * t / a); 104 //cerr << z1 << " " << x1 << " " << t1 << " " << z2 << " " << x2 << " " << t2 << endl; 105 if(1ll * -x * f * t % b == 0) t1--; 106 return t2 - t1 < 0 ? 0 : t2 - t1; 107 } 108 void solve() { 109 cin >> a >> b; 110 ll res = 0; 111 //if(a % b == 0) res++; 112 for (int i = b; i <= a; i += b) { 113 //int now = a - b; 114 for (int j = 1; ; j++) { 115 int now = a - i * j; 116 if(now < 0) break; 117 res += work2(i + 1, i + 2, now); 118 } 119 120 //cout << i << " " << res << endl; 121 } 122 cout << res << endl; 123 } 124 int main() { 125 freopen("test.in", "r", stdin); 126 freopen("test.out", "w", stdout); 127 //freopen("test.err", "w", stderr); 128 //cout << __builtin_popcount(11) << endl; 129 //return 1; 130 //cout << work(2, 3, 5) << endl; 131 //return 0; 132 int _; 133 cin >> _; 134 for (int i = 1; i <= _; i++) { 135 cout << "Case #" << i << ": "; 136 solve(); 137 } 138 return 0; 139 }