一道中国剩余定理加上搜索的题目。分两种情况来考虑,当组合总数比较大的时候,就选择枚举的方式,组合总数的时候比较小时就选择搜索然后用中国剩余定理求出得数。
代码如下:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <set> 7 8 using namespace std; 9 10 typedef long long LL; 11 12 const int N = 11; 13 const int UB = 11111; 14 int X[N], C, S; 15 LL ans[UB], R[N]; 16 set<int> Y[N]; 17 #define ITOR iterator 18 19 template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a;} 20 void gcd(LL a, LL b, LL &d, LL &x, LL & y) { 21 if (b) { gcd(b, a % b, d, y, x); y -= a / b * x;} 22 else d = a, x = 1, y = 0; 23 } 24 LL lcm(LL a, LL b) { return a / gcd(a, b) * b;} 25 26 LL cal() { 27 LL a = X[0], r = R[0] % a, d, x, y, tmp; 28 for (int i = 1; i < C; i++) { 29 gcd(a, X[i], d, x, y); 30 if ((R[i] - r) % d) return -1; 31 tmp = a * x * ((R[i] - r) / d) + r; 32 a = lcm(a, X[i]); 33 r = (tmp % a + a) % a; 34 } 35 return r ? r : a + r; 36 } 37 38 void dfs(int p) { 39 if (p == C) { 40 LL tmp = cal(); 41 if (~tmp) ans[++ans[0]] = tmp; 42 return ; 43 } 44 set<int>::ITOR si; 45 for (si = Y[p].begin(); si != Y[p].end(); si++) { 46 R[p] = *si; 47 dfs(p + 1); 48 } 49 } 50 51 void workdfs() { 52 LL LCM = 1; 53 for (int i = 0; i < C; i++) LCM = lcm(LCM, X[i]); 54 ans[0] = 0; 55 dfs(0); 56 sort(ans + 1, ans + ans[0] + 1); 57 ans[0] = (int) (unique(ans + 1, ans + ans[0] + 1) - ans - 1); 58 int mk = ans[0]; 59 while (ans[0] < S) ans[ans[0] + 1] = ans[ans[0] + 1 - mk] + LCM, ans[0]++; 60 } 61 62 bool test(LL x) { 63 for (int i = 0; i < C; i++) { 64 if (Y[i].find(x % X[i]) == Y[i].end()) return false; 65 } 66 return true; 67 } 68 69 void workenum(int mk) { 70 set<int>::ITOR si; 71 ans[0] = 0; 72 for (int t = 0; ans[0] < S; t++) { 73 for (si = Y[mk].begin(); si != Y[mk].end() && ans[0] < S; si++) { 74 LL cur = (LL) t * X[mk] + *si; 75 if ( cur && test(cur)) ans[++ans[0]] = cur; 76 } 77 } 78 } 79 80 int main() { 81 while (~scanf("%d%d", &C, &S) && (C || S)) { 82 int mk = 0, tt = 1, y, k; 83 bool enm = false; 84 for (int i = 0; i < C; i++) { 85 scanf("%d%d", X + i, &k); 86 Y[i].clear(); 87 for (int j = 1; j <= k; j++) { 88 scanf("%d", &y); 89 Y[i].insert(y); 90 } 91 if (k * X[i] < k * X[mk]) mk = i; 92 tt *= k; 93 if (tt > UB) enm = true; 94 } 95 if (enm) workenum(mk); 96 else workdfs(); 97 ans[0] = min(ans[0], (LL) S); 98 for (int i = 1; i <= ans[0]; i++) printf("%lld ", ans[i]); 99 puts(""); 100 } 101 return 0; 102 }
——written by Lyon