uva 11754 Code Feat (中国剩余定理)

UVA 11754

  一道中国剩余定理加上搜索的题目。分两种情况来考虑,当组合总数比较大的时候,就选择枚举的方式,组合总数的时候比较小时就选择搜索然后用中国剩余定理求出得数。

代码如下:

  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 }
View Code

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/uva_11754_Lyon.html