题意概述:
有一个正整数$N$满足$C$个条件,每个条件都形如“它除以$X$的余数在集合${Y_1, Y_2, ..., Y_k}$中”,所有条件中的$X$两两互质,
你的任务是找出最小的S个解。
数据范围:
$1leq Cleq9, 1 leq S leq 10, X geq 2, 1 leq k leq 100, 0 leq Y_i leq X$
分析:
如果每个集合元素个数为1,那么我们直接使用中国剩余定理求解即可。
因此我们想到枚举余数,但是余数的组合最多会有$100^9$种可能,太多了。我们发现加入$k$的积不大的话,使用这种方法是可行的。比如
我们假设每个集合元素都不超过5。而当集合元素增加时,由于可行解是在模$M = prod X_i$下的在枚举复杂度提高的同时也意味着可行解在
数轴上变得稠密,这意味着我们可以通过从小到大枚举答案并判定的方法解决。为了加快此过程,我们希望不可行的枚举尽快被否定,因此我们
希望首先使用$k$较小并且$X$较大的条件判定,因为这个条件是更强的,于是考虑按照$frac{k}{X}$从小到大的顺序检验答案$i$是否满足当前
条件。由此问题便可解决。

1 #include <algorithm> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <queue> 6 #include <map> 7 #include <set> 8 #include <ctime> 9 #include <cmath> 10 #include <iostream> 11 #include <assert.h> 12 #define pi acos(-1.) 13 using namespace std; 14 typedef long long ll; 15 const int int_inf = 0x3f3f3f3f; 16 const ll ll_inf = 0x3f3f3f3f3f3f3f3f; 17 const int INT_INF = (int)((1ll << 31) - 1); 18 const int mod = 1e9 + 9; 19 const double double_inf = 1e30; 20 typedef unsigned long long ul; 21 #pragma comment(linker, "/STACK:102400000,102400000") 22 #define max(a, b) ((a) > (b) ? (a) : (b)) 23 #define min(a, b) ((a) < (b) ? (a) : (b)) 24 #define mp make_pair 25 #define st first 26 #define nd second 27 #define keyn (root->ch[1]->ch[0]) 28 #define lson (u << 1) 29 #define rson (u << 1 | 1) 30 #define pii pair<int, int> 31 #define pll pair<ll, ll> 32 #define pb push_back 33 #define type(x) __typeof(x.begin()) 34 #define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++) 35 #define FOR(i, s, t) for(int i = (s); i <= (t); i++) 36 #define ROF(i, t, s) for(int i = (t); i >= (s); i--) 37 #define dbg(x) cout << x << endl 38 #define dbg2(x, y) cout << x << " " << y << endl 39 #define clr(x, i) memset(x, (i), sizeof(x)) 40 #define maximize(x, y) x = max((x), (y)) 41 #define minimize(x, y) x = min((x), (y)) 42 #define low_bit(x) ((x) & (-x)) 43 44 inline int readint(){ 45 int x; 46 scanf("%d", &x); 47 return x; 48 } 49 50 inline int readstr(char *s){ 51 scanf("%s", s); 52 return strlen(s); 53 } 54 55 class cmpt{ 56 public: 57 bool operator () (const int &x, const int &y) const{ 58 return x > y; 59 } 60 }; 61 62 int Rand(int x, int o){ 63 //if o set, return [1, x], else return [0, x - 1] 64 if(!x) return 0; 65 int tem = (int)((double)rand() / RAND_MAX * x) % x; 66 return o ? tem + 1 : tem; 67 } 68 69 void data_gen(){ 70 srand(time(0)); 71 freopen("in.txt", "w", stdout); 72 int times = 100; 73 printf("%d ", times); 74 while(times--){ 75 int r = Rand(1000, 1), a = Rand(1000, 1), c = Rand(1000, 1); 76 int b = Rand(r, 1), d = Rand(r, 1); 77 int m = Rand(100, 1), n = Rand(m, 1); 78 printf("%d %d %d %d %d %d %d ", n, m, a, b, c, d, r); 79 } 80 } 81 82 struct cmpx{ 83 bool operator () (int x, int y) { return x > y; } 84 }; 85 int debug = 1; 86 int dx[] = {-1, 1, 0, 0}; 87 int dy[] = {0, 0, -1, 1}; 88 //------------------------------------------------------------------------- 89 int C, S; 90 ll mt[15][110]; 91 ll X[15], k[15]; 92 ll ans[50]; 93 ll buf[50]; 94 ll w[15], _w[15]; 95 ll M; 96 int id[15]; 97 pair<pll, int> _buf[15]; 98 const int lim = 1e5; 99 100 void egcd(ll a, ll b, ll &d, ll &x, ll &y){ 101 if(!b){ 102 d = a, x = 1, y = 0; 103 return; 104 } 105 egcd(b, a % b, d, x, y); 106 ll x1 = x, y1 = y; 107 x = y1, y = x1 - a / b * y1; 108 } 109 110 void dfs(int pos){ 111 if(pos == C + 1){ 112 ll tem = 0; 113 FOR(i, 1, C) tem += buf[i] * w[i] % M * _w[i] % M, tem %= M; 114 if(!tem) tem = M; 115 FOR(i, 0, S - 1) ans[i + S] = tem + M * i; 116 sort(ans, ans + 2 * S); 117 return; 118 } 119 FOR(i, 1, k[pos]){ 120 buf[pos] = mt[pos][i]; 121 dfs(1 + pos); 122 } 123 } 124 125 bool cmp(pair<pll, int> x, pair<pll, int> y){ 126 return x.st.st * y.st.nd < x.st.nd * y.st.st; 127 } 128 129 void enu_solve(){ 130 FOR(i, 1, C) _buf[i] = mp(mp(k[i], X[i]), i); 131 sort(_buf + 1, _buf + C + 1); 132 FOR(i, 1, C) id[i] = _buf[i].nd; 133 int cnt = 0; 134 int bg = 1; 135 while(cnt < S){ 136 int ok1 = 1; 137 FOR(i, 1, C){ 138 int j = id[i]; 139 int tem = bg % X[j]; 140 int sz = k[j]; 141 int ok = 0; 142 FOR(u, 1, sz) if(tem == mt[j][u]) { ok = 1; break; } 143 if(!ok) { ok1 = 0; break; } 144 } 145 if(ok1) ans[cnt++] = bg; 146 bg++; 147 } 148 } 149 150 void crt_solve(){ 151 M = 1; 152 FOR(i, 1, C) M *= X[i]; 153 FOR(i, 1, C) w[i] = M / X[i] % M; 154 FOR(i, 1, C){ 155 ll d, x, y; 156 egcd(w[i], X[i], d, x, y); 157 _w[i] = (x % X[i] + X[i]) % X[i]; 158 } 159 clr(ans, ll_inf); 160 dfs(1); 161 } 162 163 void solve(){ 164 ll num = 1; 165 int ok = 1; 166 FOR(i, 1, C){ 167 num *= k[i]; 168 if(num > lim){ 169 ok = 0; 170 break; 171 } 172 } 173 if(ok) crt_solve(); 174 else enu_solve(); 175 } 176 177 //------------------------------------------------------------------------- 178 int main(){ 179 //data_gen(); return 0; 180 //C(); return 0; 181 debug = 0; 182 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// 183 if(debug) freopen("in.txt", "r", stdin); 184 //freopen("out.txt", "w", stdout); 185 while(~scanf("%d%d", &C, &S) && C){ 186 FOR(i, 1, C){ 187 X[i] = readint(), k[i] = readint(); 188 FOR(j, 1, k[i]) mt[i][j] = readint(); 189 } 190 solve(); 191 FOR(i, 0, S - 1) printf("%lld ", ans[i]); 192 printf(" "); 193 } 194 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 195 return 0; 196 }