中国剩余定理的应用
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::istringstream; using std::make_pair; using std::greater; using std::endl; typedef long long LL; const int MAXN(110); template<typename T> struct SBT { struct NODE { T key; int size; NODE *left, *right; }; NODE pool[MAXN]; NODE *root, *NIL, *rear; T tkey; void init() { NIL = pool; NIL->left = NIL->right = NIL; NIL->size = 0; rear = pool+1; root = NIL; } void newnode(NODE *&sour, const T &value) { rear->key = value; rear->size = 1; rear->left = rear->right = NIL; sour = rear++; } void left_rotate(NODE *&sour) { NODE *temp = sour->right; sour->right = temp->left; temp->left = sour; temp->size = sour->size; sour->size = sour->left->size+sour->right->size+1; sour = temp; } void right_rotate(NODE *&sour) { NODE *temp = sour->left; sour->left = temp->right; temp->right = sour; temp->size = sour->size; sour->size = sour->left->size+sour->right->size+1; sour = temp; } void maintain(NODE *&sour, bool flag) { if(flag == false) { if(sour->left->left->size > sour->right->size) right_rotate(sour); else if(sour->left->right->size > sour->right->size) { left_rotate(sour->left); right_rotate(sour); } else return; } else { if(sour->right->right->size > sour->left->size) left_rotate(sour); else if(sour->right->left->size > sour->left->size) { right_rotate(sour->right); left_rotate(sour); } else return; } maintain(sour->left, false); maintain(sour->right, true); maintain(sour, false); maintain(sour, true); } void insert(const T &value) { tkey = value; insert_(root); } void insert_(NODE *&sour) { if(sour == NIL) { newnode(sour, tkey); return ; } ++sour->size; if(tkey < sour->key) insert_(sour->left); else insert_(sour->right); maintain(sour, tkey >= sour->key); } NODE *search(const T &value) { NODE *sour = root; while(sour != NIL && value != sour->key) { if(value < sour->key) sour = sour->left; else sour = sour->right; } return sour; } }; void ex_gcd(LL a, LL b, LL &x, LL &y, LL &g) { if(!b) { g = a; x = 1; y = 0; return ; } ex_gcd(b, a%b, y, x, g); y -= x*(a/b); } LL inv(LL a, LL n) { LL ret, temp, g; ex_gcd(a, n, ret, temp, g); return g == 1LL? (ret+n)%n: -1; } LL pow_mod(LL a, LL p, LL n) { LL ret = 1LL; for(int i = 0; (1LL << i) <= p; a = a*a%p) if(p&(1LL << i)) ret = ret*a%p; return ret; } LL china(int n, int *a, int *m) { LL M = 1LL, ret = 0LL, x, y, g; for(int i = 0; i < n; ++i) M *= m[i]; for(int i = 0; i < n; ++i) { LL w = M/m[i]; ex_gcd(w, m[i], x, y, g); ret = (ret+x*w*a[i])%M; } return (ret+M)%M; } int C, S; int Y[10][100]; int quant[10]; int X[10]; const int LIMIT(10000); SBT<int> st[10]; void solve_enum(int best) { int count = 0; for(int i = 0; i < C; ++i) if(i != best) { st[i].init(); for(int j = 0; j < quant[i]; ++j) st[i].insert(Y[i][j]); } sort(Y[best], Y[best]+quant[best]); for(int i = 0; count != S; ++i) for(int j = 0; j < quant[best]; ++j) { LL temp = Y[best][j]+(LL)X[best]*i; if(temp == 0LL) continue; bool flag = true; for(int i = 0; i < C; ++i) if(i != best && st[i].search(temp%X[i]) == st[i].NIL) { flag = false; break; } if(flag) { printf("%lld\n", temp); if(++count == S) break; } } } vector<int> ans; int arr[10]; void dfs(int dep) { if(dep == C) ans.push_back(china(C, arr, X)); else { for(int i = 0; i < quant[dep]; ++i) { arr[dep] = Y[dep][i]; dfs(dep+1); } } } void solve_china() { ans.clear(); dfs(0); sort(ans.begin(), ans.end()); LL M = 1LL; for(int i = 0; i < C; ++i) M *= X[i]; int count = 0; for(int i = 0; count != S; ++i) for(int j = 0; j < ans.size(); ++j) { LL temp = ans[j]+M*i; if(temp > 0LL) { printf("%lld\n", temp); if(++count == S) break; } } } int main() { while(scanf("%d%d", &C, &S), C+S) { int best = 0, tot = 1; for(int i = 0; i < C; ++i) { scanf("%d%d", X+i, quant+i); for(int j = 0; j < quant[i]; ++j) scanf("%d", Y[i]+j); if(quant[i]*X[best] < quant[best]*X[i]) best = i; tot *= quant[i]; } if(tot > LIMIT) solve_enum(best); else solve_china(); putchar('\n'); } return 0; }