zoukankan      html  css  js  c++  java
  • 2014百度之星资格赛

     
    A. Energy Conversion
    小度有M点能量,打开石门需要N点能量,他可以有一个操作使用V点能量让自己当前能量变成(M-V)*K,问最少需要几次能量转换才能打开石门,打不开输出-1.
    N,M,V,K <= 10 ^ 8
    a.模拟能量转换过程,如果发现能量转换后保持不变,或者能量变小,答案就是-1,否则输出模拟后的答案。因为K肯定会大于2,所以收敛到N还是很快的。
    #define _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <vector>
    #include <queue>
    #include <cstdlib>
    #include <set>
    #include <numeric>
    using namespace std;
    
    
    
    int main() {
        int t;
        scanf("%d", &t);
        __int64 n, m, v, k, ans;
        while (t--) {
            scanf("%I64d %I64d %I64d %I64d", &n, &m, &v, &k);
            if (m >= n) ans = 0;
            else if ((m - v)*k >= n) ans = 1;
            else if (k==1) ans = -1;
            else {
    
                __int64 kk = k;
                __int64 cur = 0;
                for (int i = 1;; i++) {
                    long long val = m * kk + v * k * (kk - 1) / (1 - k);
                    if (val <= cur) {
                        ans = -1;
                        break;
                    }
                    if (val >= n) {
                        ans = i; break;
                    }
                    cur = val;
                    kk *= k;
                }
            }
            printf("%I64d
    ", ans);
        }
    }
    View Code
    b.进行数值分析,当K不等于1是,n次后能得到的能量为,我们保证它的导数是大于0,那么当f(n)=M时候,求得n就是答案。
    #define _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <vector>
    #include <queue>
    #include <cstdlib>
    #include <set>
    #include <numeric>
    using namespace std;
    
    int main() {
        int t;
        scanf("%d", &t);
        double n, m, v, k;
        int ans;
        while (t--) {
            scanf("%lf %lf %lf %lf", &n, &m, &v, &k);
            if (m >= n) ans = 0;
            else if ((m - v)*k >= n) ans = 1;
            else {
                if (k == 1) {
                    ans = -1;
                }
                else {
                    if (m + v * k /(1 - k) <= 0) ans = -1;
                    else {
                        ans = ceil(log(((1 - k)*n + v*k) / ((1 - k)*m + v*k)) / log(k));
                        if (ans < 2)    ans = -1;
                    }
                }
            }
            printf("%d
    ", ans);
        }
    }
    View Code

    B. Disk Schedule

    双调路径,DP动态规划

    C. Xor Num

    描述:

    Problem Description

    Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?
     
    Input
    输入包含若干组测试数据,每组测试数据包含若干行。
    输入的第一行是一个整数T(T < 10),表示共有T组数据。
    每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。

    思路:对于一个正整数S如何找一个数X,让S ^ X最大,最简单的方法就是,X的每一位与S的每一位是相反的。那么对于S集合中的所有数就可以构造一棵Trie树进行记录,寻找时候就S当前位取反的方向向下查找(如果存在,否则向另一个方向),直到遍历完S的每一位,也就从Trie树得到答案。构造Trie树的复杂度为O(32*N),每次查询的复杂度为O(32),Trie空间复杂度理论为(2^32),但是最多只有N个整数,所以是不会太大。

    #define _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <vector>
    #include <queue>
    #include <cstdlib>
    #include <set>
    #include <numeric>
    #include <bitset>
    using namespace std;
    
    const int branchNum = 2;//字数的个数
    class TrieNode
    {
    public:
        TrieNode *next[branchNum];
        TrieNode()
        {
            memset(next, NULL, sizeof(next));
        }
    };
    
    class Trie
    {
    public:
        Trie();
        void Insert(int val);
        unsigned long Find(int val);
        void DeleteTrie(TrieNode *root);
        TrieNode *Root;
    };
    
    Trie::Trie()
    {
        Root = new TrieNode();
    }
    
    void Trie::Insert(int val)
    {
        TrieNode *location = Root;
        for (int i = 31; i >= 0; i--)
        {
            int v = val >> i;
            if (location->next[v & 0x01] == NULL)//不存在就建立节点
            {
                TrieNode *tmp = new TrieNode();
                location->next[v & 0x01] = tmp;
            }
            location = location->next[v & 0x01];
        }
    }
    
    unsigned long Trie::Find(int val)
    {
        bitset<32> res;
        TrieNode *location = Root;
        for (int i = 31; i >= 0; i--)
        {
            int v = val >> i;
            if (v & 0x01)
            {
                if (location->next[0] != NULL)
                {
                    location = location->next[0];
                    res[i] = 0;
                }
                else 
                {
                    location = location->next[1];
                    res[i] = 1;
                }
            }
            else
            {
                if (location->next[1] != NULL)
                {
                    location = location->next[1];
                    res[i] = 1;
                }
                else
                {
                    location = location->next[0];
                    res[i] = 0;
                }
            }
        }
        return res.to_ulong();
    }
    
    void Trie::DeleteTrie(TrieNode *root)
    {
        for (int i = 0; i < branchNum; ++i)
        {
            if (root->next[i] != NULL)
            {
                DeleteTrie(root->next[i]);
            }
        }
        delete root;
    }
    
    
    
    int main()
    {
        int t, n, m, i, e;
        scanf("%d", &t);
        for (int Cas = 1; Cas <= t; Cas++)
        {
            scanf("%d %d", &n, &m);
            Trie t;
            for (i = 0; i < n; i++) {
                scanf("%d", &e);
                t.Insert(e);
            }
            printf("Case #%d:
    ", Cas);
            while (m--)
            {
                scanf("%d", &e);
                printf("%u
    ", t.Find(e));
            }
        }
        return 0;
    }
    View Code

    D. Labyrinth

    题意就是给定一个矩阵,每个单元元素可以使正、负、0,起始点在左上角,终止点在右上角,每次只能上、下、右三种移动方式,并且一个格子只能走一次,问得到的最大值。

    用动态规划来求解,定义dp[i][j],代表从(1, 1)走到第(i, j)个格子时候得到的最大值,那么最后的答案就是dp[1][m]。

    现在只考虑两列:

    我们要求dp[i][j]的值,它可以来自于J-1列的各个单元,那么可以得到递推的方程如下:

    其中k是枚举第j-1列的各行单元,v代表矩阵中存储的值,sum(k, i-1),代表求第j列的第k行到i-1行的和。由于每一列只和前面的一列相关,还可以用滚动数组来进行空间优化的。

    那么最后得到dp[1][m]就是需要的值。

    #define _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <vector>
    #include <queue>
    #include <cstdlib>
    #include <set>
    #include <numeric>
    #include <bitset>
    using namespace std;
    
    const int maxn = 105;
    int e[maxn][maxn];
    int dp[maxn][maxn];
    int sum[maxn][maxn];
    
    int main()
    {
        int t, i, j, k, r, c;
        scanf("%d", &t);
        for (int Cas = 1; Cas <= t; Cas++) {
            scanf("%d %d", &r, &c);
            for (i = 1; i <= r; i++)
            for (j = 1; j <= c; j++)
                scanf("%d", &e[i][j]);
    
            memset(sum, 0, sizeof(sum));
            for (i = 1; i <= c; i++)
            for (j = 1; j <= r; j++) {
                sum[j][i] = sum[j - 1][i] + e[j][i];
            }
    
            memset(dp, 0, sizeof(dp));
            dp[1][1] = e[1][1]; 
            for (i = 1; i <= r; i++) {
                dp[i][1] = dp[i - 1][1]+e[i][1];
            }
    
    
    
            for (i = 2; i <= c; i++)
            for (j = 1; j <= r; j++) {
                dp[j][i] = -0x3fffffff;
                for (k = 1; k <= r; k++) {
                    int tmp;
                    if (k == j) {
                        tmp = e[j][i];
                    } else if (k > j) {
                        tmp = sum[k][i] - sum[j][i] + e[j][i];
                    } else {
                        tmp = sum[j - 1][i] - sum[k - 1][i] + e[j][i];
                    }
                    dp[j][i] = max(dp[j][i], dp[k][i - 1] + tmp);
                }
            }
            printf("Case #%d:
    ", Cas);
            printf("%d
    ", dp[1][c]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    github的使用
    QPalette的用法
    QTimer的用法
    QStatusBar的用法
    QWhatsThis的用法
    QString::​arg的用法
    qt中ui的 使用介绍
    安全协议IPSEC
    安全协议ssl
    对称加密和非对称加密
  • 原文地址:https://www.cnblogs.com/tiny656/p/3741899.html
Copyright © 2011-2022 走看看