题目大意:求一个数N,给出C和S,表示有C个条件,每个条件有X 和 k,然后是该个条件的k个yi,即NmodX=yj,输出满足的最小的S个N,要求正整数。
解题思路:total为所有的k的乘积,也就是可以作为一组完整限定条件的可能数,当个确定条件可以用中国剩余定理处理。但是如果total太大的话,处理的情况比较多。不过total数大的时候,可以通过枚举N来判断,找到一组k/x最小的最为枚举基准,然后判断即可。
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxc = 15;
const int maxk = 105;
const int limit = 10000;
ll total;
int C, S, X[maxc], k[maxc];
int bestc, Y[maxc][maxk];
set<int> vis[maxc];
void init () {
total = 1;
bestc = 0;
for (int i = 0; i < C; i++) {
scanf("%d%d", &X[i], &k[i]);
total *= k[i];
for (int j = 0; j < k[i]; j++)
scanf("%d", &Y[i][j]);
sort(Y[i], Y[i] + k[i]);
if (k[i] * X[bestc] < k[bestc] * X[i])
bestc = i;
}
}
void solveEnum (int s) {
for (int i = 0; i < C; i++) {
if (i == s)
continue;
vis[i].clear();
for (int j = 0; j < k[i]; j++)
vis[i].insert(Y[i][j]);
}
for (int t = 0; S; t++) {
for (int i = 0; i < k[s]; i++) {
ll n = (ll)X[s] * t + Y[s][i];
if (n == 0)
continue;
bool flag = true;
for (int c = 0; c < C; c++) {
if (c == s)
continue;
if (!vis[c].count(n%X[c])) {
flag = false;
break;
}
}
if (flag) {
printf("%lld\n", n);
if (--S == 0)
break;
}
}
}
}
int a[maxc];
vector<int> sol;
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);
}
}
int china (int n, int* s, 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;
}
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 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){
printf("%lld\n", n);
if (--S == 0)
break;
}
}
}
}
int main () {
while (scanf("%d%d", &C, &S) == 2 && C + S) {
init();
if (total > limit)
solveEnum(bestc);
else
solveChina();
printf("\n");
}
return 0;
}
uva 11754 - Code Feat(中国剩余定理+暴力)
时间: 2024-10-12 20:38:34