// UVa11754 Code Feat
// Rujia Liu
typedef long long LL;
// 即使a, b在int范围内,x和y有可能超出int范围
void gcd(LL a, LL b, LL& d, LL& x, LL& y) {
if(!b){ d = a; x = 1; y = 0; }
else{ gcd(b, a%b, d, y, x); y -= x*(a/b); }
}
// n个方程:x=a[i](mod m[i]) (0<=i<n)
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];
gcd(m[i], w, d, d, y);
x = (x + y*w*a[i]) % M;
}
return (x+M)%M;
}
#include<cstdio>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
const int maxc = 9;
const int maxk = 100;
const int LIMIT = 10000;
set<int> values[maxc];
int C, X[maxc], k[maxc];
int Y[maxc][maxk];
void solve_enum(int S, int bc) {
for(int c = 0; c < C; c++) if(c != bc) {
values[c].clear();
for(int i = 0; i < k[c]; i++) values[c].insert(Y[c][i]);
}
for(int t = 0; S != 0; t++) {
for(int i = 0; i < k[bc]; i++) {
LL n = (LL)X[bc]*t + Y[bc][i];
if(n == 0) continue; // 只输出正数解
bool ok = true;
for(int c = 0; c < C; c++) if(c != bc)
if(!values[c].count(n % X[c])) { ok = false; break; }
if(ok) { printf("%lld\n", n); if(--S == 0) break; }
}
}
}
int a[maxc]; // 搜索对象,用于中国剩余定理
vector<LL> sol;
void dfs(int dep) {
if(dep == C)
sol.push_back(china(C, a, X));
else for(int i = 0; i < k[dep]; i++) {
a[dep] = Y[dep][i];
dfs(dep + 1);
}
}
void solve_china(int S) {
sol.clear();
dfs(0);
sort(sol.begin(), sol.end());
LL M = 1;
for(int i = 0; i < C; i++) M *= X[i];
vector<LL> ans;
for(int i = 0; S != 0; i++) {
for(int j = 0; j < sol.size(); j++) {
LL n = M*i + sol[j];
if(n > 0) { printf("%lld\n", n); if(--S == 0) break; }
}
}
}
int main() {
int S;
while(scanf("%d%d", &C, &S) == 2 && C) {
LL tot = 1;
int bestc = 0;
for(int c = 0; c < C; c++) {
scanf("%d%d", &X[c], &k[c]);
tot *= k[c];
for(int i = 0; i < k[c]; i++) scanf("%d", &Y[c][i]);
sort(Y[c], Y[c]+k[c]);
if(k[c]*X[bestc] < k[bestc]*X[c]) bestc = c;
}
if(tot > LIMIT) solve_enum(S, bestc);
else solve_china(S);
printf("\n");
}
return 0;
}
书上的代码;
题目大意:求一个数N,给出C和S,表示有C个条件,每个条件有X 和 k,然后是该个条件的k个yi,即NmodX=yj,输出满足的最小的S个N,要求正整数。
解题思路:total为所有的k的乘积,也就是可以作为一组完整限定条件的可能数,当个确定条件可以用中国剩余定理处理。但是如果total太大的话,处理的情况比较多。不过total数大的时候,可以通过枚举N来判断,找到一组k/x最小的最为枚举基准,然后判断即可。