uva 11754 - Code Feat(中国剩余定理+暴力)

题目链接:uva 11754 - Code Feat

题目大意:求一个数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

uva 11754 - Code Feat(中国剩余定理+暴力)的相关文章

UVA 11754 - Code Feat(数论)

UVA 11754 - Code Feat 题目链接 题意:给定一个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 <stdio.h> #include <string.

UVA 11754 Code Feat (枚举,中国剩余定理)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud C Code Feat   The government hackers at CTU (Counter-Terrorist Unit) have learned some things about the code, but they still haven't quite solved it.They know it's a single, strictly positive

Uva 11754 Code Feat

题意概述: 有一个正整数$N$满足$C$个条件,每个条件都形如“它除以$X$的余数在集合$\{Y_1, Y_2, ..., Y_k\}$中”,所有条件中的$X$两两互质, 你的任务是找出最小的S个解. 数据范围: $1\leq C\leq9, 1 \leq S \leq 10, X \geq 2, 1 \leq k \leq 100, 0 \leq Y_i \leq X$ 分析: 如果每个集合元素个数为1,那么我们直接使用中国剩余定理求解即可. 因此我们想到枚举余数,但是余数的组合最多会有$10

UVA - 11754 Code Feat (分块+中国剩余定理)

对于一个正整数N,给出C组限制条件,每组限制条件为N%X[i]∈{Y1,Y2,Y3,...,Yk[i]},求满足条件的前S小的N. 这道题很容易想到用中国剩余定理,然后用求第k小集合的方法输出答案.但是一取模,孰大孰小就不好控制了,所以行不通.直接枚举所有情况的话,总方案数(所有k的乘积)高达C*k,显然也是不行的. 还有一种方法是枚举所有可能的N,然后检验是否满足条件.对于每个满足条件的N,任取某个限制条件i,对于其中某个余数j,都可以写成X[i]*t+Y[i][j]的形式.复杂度未知,但总方

UVA11754 - Code Feat

Hooray!  Agent Bauer has shot the terrorists, blown upthe bad guy base, saved the hostages, exposed the moles in the government,prevented an environmental catastrophe, and found homes for three orphanedkittens, all in the span of 19 consecutive hours

UVa 11754 (中国剩余定理 枚举) Code Feat

如果直接枚举的话,枚举量为k1 * k2 *...* kc 根据枚举量的不同,有两种解法. 枚举量不是太大的话,比如不超过1e4,可以枚举每个集合中的余数Yi,然后用中国剩余定理求解.解的个数不够S个的时候,要把这些解分别加上M.2M...(M = X1 * X2 *...* Xc) 如果上述枚举量太大的话,直接枚举x.找一个k/X最小的条件,然后让x = t * X + Yi开始枚举,因为这样枚举x增长得最快,所以枚举次数也就最少.如果符合要求的话则输出. 上面两种方法都要注意所找到的解为正整

UVA 11754 (暴力+中国剩余定理)

题目链接: http://www.bnuoj.com/v3/problem_show.php?pid=20172 题目大意:有C个模方程,每个方程可能有k余数,求最小的S个解. 解题思路: 看见模方程就想到中国剩余定理,然后看下确定的方程情况. 由乘法原理,共有II ki 种情况,即求解II ki 次.k比较大时基本完蛋. 其实解模方程还有一种暴力方法,就是选定一个模方程,令t=0,1...., n=t*LCM+余数(n一定要大于0) 通过t不断增大这种迭代方式从小到大创造一些可能解n,然后去测

uva 756 - Biorhythms(中国剩余定理)

题目链接:uva 756 - Biorhythms 题目大意:三个周期,23,28,33,输入为分别为在新一年中(三个周期均从0开始),出现周期中峰值的一天,以及当前的日子,问说需要经过多少天,才能使得三个峰值的在同一天. 解题思路:裸的中国剩余定理. #include <cstdio> #include <cstring> typedef long long ll; const int maxn = 5; const ll m[maxn] = {23,28,33}; ll M,

对于中国剩余定理(CRT)的初步理解

以前觉得用中国剩余定理来求同余方程组很鸡肋,因为可以用拓展欧几里得算法来构造出一种更加强大(可以处理取模的数(默认为mi)不互质的情况)的算法. 今天查了点资料,发现我太天真了. 首先讲讲中国剩余定理: 即 : x ≡ a[i] (mod m[i]) 1<= i <= r (m[i] 两两互质) 求这个同余方程组可以快速算: x = ∑M/m[i] * Inv(M/m[i], m[i]) * a[i] (mod M) 其中M = m[1]*m[2]*m[3]...m[r]  , Inv(x,