题意:给定一个c个x, y1,y2,y3..yk形式,前s小的答案满足s % x在集合y1, y2, y3 ... yk中
思路:LRJ大白例题,分两种情况讨论
1、所有x之积较小时候,暴力枚举每个集合选哪个y,然后中国剩余定理求解
2、所有x之积较大时候,选定一个k/x尽可能小的序列,枚举x * t + y (t = 1, 2, 3...)去暴力求解。
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif
#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)
const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));
const int maxc = 20;
const int maxs = 20;
const int maxk = 100 + 20;
int C, S;
int X[maxc], K[maxc];
int G[maxc][maxk];
int ans[maxs];
int sel[maxc];
vector<LL> sol;
void extendedGcd(LL a, LL b, LL & d, LL & x, LL & y) {
if(!b) { d = a; x = 1; y = 0; }
else { extendedGcd(b, a%b, d, y, x); y -= x*(a/b); }
}
LL china(int n, int * a, int * m) {
LL M = 1, d, y, x = 0;
for(int i=0; i<n; i++) M *= m[i];
for(int i=0; i<n; i++) {
LL w = M / m[i];
extendedGcd(m[i], w, d, d, y);
x = (x + y*w*a[i]) % M;
}
return (x+M) % M;
}
void dfs(int cur) {
if(cur == C) {
LL tans = china(C, sel, X);
sol.push_back(tans);
return ;
}
for(int i=0; i<K[cur]; i++) {
sel[cur] = G[cur][i];
dfs(cur+1);
}
}
void solveChina() {
sol.clear();
dfs(0);
sort(sol.begin(), sol.end());
LL M = 1;
for(int i=0; i<C; i++) M *= X[i];
for(int i=0; S; i++) {
for(int j=0; j<sol.size(); j++) {
LL n = M * i + sol[j];
if(n > 0) { P64I(n); if(--S == 0) break; }
}
}
}
set<int> values[maxc];
void solveEnum(int bc) {
for(int i=0; i<C; i++) if(i != bc) {
values[i].clear();
for(int j=0; j<K[i]; j++) values[i].insert(G[i][j]);
}
for(int t = 0; S; t++) {
for(int i=0; i<K[bc]; i++) {
LL x = (LL)t * X[bc] + G[bc][i];
if(!x) continue;
bool ok = true;
for(int c=0; c<C; c++) if(c != bc) {
if(!values[c].count(x%X[c])) { ok = false; break; }
}
if(ok) { P64I(x); if(--S == 0) break; }
}
}
}
int main() {
while(scanf("%d%d", &C, &S) != EOF && C) {
int totK = 1;
int tmini = 0;
for(int i=0; i<C; i++) {
scanf("%d%d", &X[i], &K[i]);
totK *= K[i];
if(K[i] * X[tmini] < X[i] * K[tmini]) tmini = i;
for(int j=0; j<K[i]; j++) {
scanf("%d", &G[i][j]);
}
sort(G[i], G[i]+K[i]);
}
if(totK <= 10000) solveChina();
else solveEnum(tmini);
putchar('\n');
}
return 0;
}