UVa 11754 (中国剩余定理 枚举) Code Feat

如果直接枚举的话,枚举量为k1 * k2 *...* kc

根据枚举量的不同,有两种解法。

  • 枚举量不是太大的话,比如不超过1e4,可以枚举每个集合中的余数Yi,然后用中国剩余定理求解。解的个数不够S个的时候,要把这些解分别加上M、2M...(M = X1 * X2 *...* Xc)
  • 如果上述枚举量太大的话,直接枚举x。找一个k/X最小的条件,然后让x = t * X + Yi开始枚举,因为这样枚举x增长得最快,所以枚举次数也就最少。如果符合要求的话则输出。

上面两种方法都要注意所找到的解为正整数。

  1 typedef long long LL;

  2 

  3 void gcd(LL a, LL b, LL& d, LL& x, LL& y)

  4 {

  5     if(!b) { d = a; x = 1; y = 0; }

  6     else { gcd(b, a%b, d, y, x); y -= x*(a/b); }

  7 }

  8 

  9 LL china(int n, int* a, int* m)

 10 {

 11     LL M = 1, d, y, x = 0;

 12     for(int i = 0; i < n; i++) M *= m[i];

 13     for(int i = 0; i < n; i++)

 14     {

 15         LL w = M / m[i];

 16         gcd(m[i], w, d, d, y);

 17         x = (x + y*w*a[i]) % M;

 18     }

 19     return (x+M)%M;

 20 }

 21 

 22 #include <cstdio>

 23 #include <vector>

 24 #include <set>

 25 #include <algorithm>

 26 #include <cstring>

 27 using namespace std;

 28 

 29 const int maxc = 9;

 30 const int maxk = 100;

 31 const int LIMIT = 10000;

 32 int C, S;

 33 int bestc;

 34 int X[maxc], Y[maxc][maxk], k[maxc];

 35 set<int> values[maxc];

 36 

 37 void solve_enum()

 38 {

 39     for(int c = 0; c < C; c++) if(c != bestc)

 40     {

 41         values[c].clear();

 42         for(int i = 0; i < k[c]; i++)

 43             values[c].insert(Y[c][i]);

 44     }

 45 

 46     for(int t = 0; S != 0; t++)

 47     {

 48         for(int i = 0; i < k[bestc]; i++)

 49         {

 50             LL n = (LL)t * X[bestc] + Y[bestc][i];//枚举解

 51             if(n == 0) continue;

 52             bool ok = true;

 53             for(int c = 0; c < C; c++) if(c != bestc)//判断是否符合要求

 54                 if(!values[c].count(n % X[c])) { ok = false; break; }

 55             if(ok) { printf("%lld\n", n); if(--S == 0) { break; } }

 56         }

 57     }

 58 }

 59 

 60 int a[maxc];

 61 vector<LL> sol;

 62 

 63 void dfs(int d)

 64 {

 65     if(d == C) sol.push_back(china(C, a, X));

 66     else for(int i = 0; i < k[d]; i++)

 67     {

 68         a[d] = Y[d][i];

 69         dfs(d + 1);

 70     }

 71 }

 72 

 73 void solve_china()

 74 {

 75     sol.clear();

 76     dfs(0);

 77     sort(sol.begin(), sol.end());

 78 

 79     LL M = 1;

 80     for(int i = 0; i < C; i++) M *= X[i];

 81 

 82     for(int i = 0; S != 0; i++)

 83     {

 84         for(int j = 0; j < sol.size(); j++)

 85         {

 86             LL n = M * i + sol[j];

 87             if(n == 0) continue;

 88             printf("%lld\n", n);

 89             if(--S == 0) break;

 90         }

 91     }

 92 }

 93 

 94 int main()

 95 {

 96     freopen("in.txt", "r", stdin);

 97 

 98     while(scanf("%d%d", &C, &S) == 2 && C && S)

 99     {

100         bestc = 0;

101         int tot = 1;

102         for(int c = 0; c < C; c++)

103         {

104             scanf("%d%d", &X[c], &k[c]);

105             tot *= k[c];

106             if(k[c] * X[bestc] < k[bestc] * X[c]) bestc = c;

107             for(int i = 0; i < k[c]; i++)

108                 scanf("%d", &Y[c][i]);

109             sort(Y[c], Y[c] + k[c]);

110         }

111 

112         if(tot > LIMIT) solve_enum();

113         else solve_china();

114         printf("\n");

115     }

116 

117     return 0;

118 }
代码君

 

你可能感兴趣的:(code)