• 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); 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);
     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("
    ");
    115     }
    116 
    117     return 0;
    118 }
    代码君
  • 相关阅读:
    MinGW离线包下载地址
    词法分析器--DFA(c++实现)
    linux下shell统计文件目录下所有代码行数
    四则运算表达式
    BliBli抢楼全攻略
    python 电影下载链接爬虫
    in, out, ref
    联合查询
    SQL语句大全
    LINQ
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4322196.html
Copyright © 2020-2023  润新知