zoukankan      html  css  js  c++  java
  • Coco dfs 或者 状压dp。...

    C -- Coco

    Time Limit:1s Memory Limit:64MByte

    Submissions:148Solved:85

    DESCRIPTION

    Coco just learned a math operation call mod.Now,there is an integer aa and nn integers b1,,bnb1,…,bn. After selecting some numbers from b1,,bnb1,…,bn in any order, say c1,,crc1,…,cr, Coco want to make sure that amodc1modc2modmodcr=0amodc1modc2mod…modcr=0 (i.e., aa will become the remainder divided by cici each time, and at the end, Coco want aa to become 00). Please determine the minimum value of rr. If the goal cannot be achieved, print 1−1 instead.

    INPUT
    The first line contains one integer T(T5)T(T≤5), which represents the number of testcases. For each testcase, there are two lines: 1. The first line contains two integers nn and aa (1n20,1a1061≤n≤20,1≤a≤106). 2. The second line contains nn integers b1,,bnb1,…,bn (1in,1bi106∀1≤i≤n,1≤bi≤106).
    OUTPUT
    Print TT answers in TT lines.
    SAMPLE INPUT
    2 2 9 2 7 2 9 6 7
    SAMPLE OUTPUT
    2 -1

    先对数组排序,从大到小,因为mod大的数,不会对MOD小的数有影响,但是因为余数比MOD小的数更大,所以因子数只会更多。机会只会更多,就像样例一样,先MOD 7,再MOD 2.

    所以用dfs枚举每一个数,MOD和不MOD都选一次。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    #define MY "H:/CodeBlocks/project/CompareTwoFile/DataMy.txt", "w", stdout
    #define ANS "H:/CodeBlocks/project/CompareTwoFile/DataAns.txt", "w", stdout
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn = 1e6 + 20;
    int a[maxn];
    int n, ans;
    int val;
    void dfs(int selct, int re, int cur) {
        if (selct >= ans) return;
        if (re == 0) {
            ans = min(ans, selct);
            return;
        }
        if (cur > n) return;
        dfs(selct + 1, re % a[cur], cur + 1);
        dfs(selct, re, cur + 1);
    }
    void work() {
        scanf("%d%d", &n, &val);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        sort(a + 1, a + 1 + n, greater<int>());
        ans = inf;
        dfs(0, val, 1);
        if (ans == inf) printf("-1
    ");
        else printf("%d
    ", ans);
    }
    
    int main() {
        freopen("data.txt","r",stdin);
        int t;
        scanf("%d", &t);
        while (t--) work();
        return 0;
    }
    View Code

    状压:dp[state]表示现在MOD了那位数字,然后枚举的时候,也是优先MOD了大的数字,再转移去小的数字。不允许先MOD小的再转移去MOD大的,就是2--3这条路径是不行的,因为2--3就是先MOD2,再MOD1得到,但是可以先MOD1,再MOD2得到。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    #define MY "H:/CodeBlocks/project/CompareTwoFile/DataMy.txt", "w", stdout
    #define ANS "H:/CodeBlocks/project/CompareTwoFile/DataAns.txt", "w", stdout
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn = 2e6 + 20;
    int dp[maxn];
    int a[maxn];
    int get(int val) {
        int ans = 0;
        while (val) {
            val &= (val - 1);
            ans++;
        }
        return ans;
    }
    int cnt[maxn];
    void init() {
        int end = (1 << 20) - 1;
        for (int i = 0; i <= end; ++i) {
            cnt[i] = get(i);
        }
        return;
    }
    void work() {
        int ans = inf;
        int n, val;
        scanf("%d%d", &n, &val);
        for (int i = 0; i < n; ++i) {
            scanf("%d", &a[i]);
        }
        sort(a, a + n, greater<int>());
        memset(dp, 0x3f, sizeof dp);
        for (int i = 0; i < n; ++i) {
            dp[1 << i] = val % a[i];
            if (dp[1 << i] == 0) ans = 1;
        }
        int end = (1 << n) - 1;
        for (int j = 1; j <= end; ++j) {
            if (cnt[j] >= ans) continue;
            for (int i = 0; i < n; ++i) {
                if (((1 << i) & j) != 0) continue;
                int state = j | (1 << i);
                if (cnt[state] >= ans) continue;
                if (dp[state] != inf) continue;
                dp[state] = dp[j] % a[i];
                if (dp[state] == 0) ans = cnt[state];
            }
        }
        if (ans == inf) printf("-1
    ");
        else printf("%d
    ", ans);
    }
    
    int main() {
        init();
        int t;
        scanf("%d", &t);
        while (t--) work();
        return 0;
    }
    View Code
  • 相关阅读:
    rails学习笔记(6)
    流程图好工具推荐JUDE
    流程图好工具推荐JUDE
    rails学习笔记(5)
    [转载 js]JsDoc Toolkit:Javascript文档利器
    ruby学习笔记(7)
    end_form_tag 已经在rails2.x中去掉了
    [转载 js]JsDoc Toolkit:Javascript文档利器
    rails学习笔记(5)
    ios 防止按钮快速点击造成多次响应的避免方法。
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6104160.html
Copyright © 2011-2022 走看看