zoukankan      html  css  js  c++  java
  • ACM学习历程—2016"百度之星"

    http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=690

    A题:

    给定字符串,求任意区间的Hash值。

    根据题目给定的Hash方式,属于乘法类型,那么就可以预处理出所有的乘法前缀,然后利用逆元,就可以得到任意区间的Hash值。

    不过在这题上跪了好久,最后讨论版的一位大神给出了一个很叼的隐含条件:“同志们,当a, b超范围的时候,输出上一次询问的答案,亲测可行。。。太坑了。。。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    #include <vector>
    #define MOD 9973
    
    using namespace std;
    
    const int maxN = 1000005;
    int q, len, ans, inv[10000], s[maxN];
    char str[maxN];
    
    void init()
    {
        //***预处理所有i在质数MOD下的逆元
        inv[1] = 1;
        for (int i = 2; i < 10000; i++)
            inv[i] = inv[MOD%i]*(MOD-MOD/i) % MOD;
    }
    
    void input()
    {
        scanf("%s", str);
        len = strlen(str);
        for (int i = 0; i < len; ++i)
        {
            if (i == 0) s[i] = (str[i]-28+MOD)%MOD;
            else s[i] = s[i-1]*(str[i]-28+MOD)%MOD;
        }
    }
    
    bool judge(int lt, int rt)
    {
        if (lt > rt) return false;
        if (lt < 1 || lt > len) return false;
        if (rt < 1 || rt > len) return false;
        return true;
    }
    
    inline int getHash(int from, int to)
    {
        return (from == 0 ? s[to] : s[to]*inv[s[from-1]]%MOD);
    }
    
    void work()
    {
        int lt, rt;
        for (int i = 0; i < q; ++i)
        {
            scanf("%d%d", &lt, &rt);
            if (judge(lt, rt))
                ans = getHash(lt-1, rt-1);
            printf("%d
    ", ans);
        }
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        //freopen("test.out", "w", stdout);
        init();
        while (scanf("%d", &q) != EOF)
        {
            input();
            work();
        }
        return 0;
    }
    View Code

    B题:

    一个递推,如果有n个1,那么要么前两个1结合,要么不结合,那么p(n) = p(n-1)+p(n-2)。然后Java大数直接打表。

    代码:

    import java.math.BigInteger;
    import java.util.Scanner;
    
    
    public class Main
    {
        BigInteger p[] = new BigInteger[205];
        
        void init()
        {
            p[1] = new BigInteger("1");
            p[2] = new BigInteger("2");
            for (int i = 3; i < 205; ++i)
                p[i] = p[i-1].add(p[i-2]);
        }
        
        public static void main(String[] args)
        {
            Scanner input = new Scanner(System.in);
            Main ans = new Main();
            int n = 0;
            ans.init();
            while (input.hasNext())
            {
                n = input.nextInt();
                System.out.println(ans.p[n]);
            }
        }
    }
    View Code

    C题:

    一道字符串前缀问题。

    有三种操作,插入一个单词,删除给定前缀的所有单词,查询是否存在给定前缀的单词。

    用字典树搞,插入的时候,给路径上所有结点的vis加1。

    删除的时候,删除前缀后面的所有子树,并将路径上所有结点的vis值,减去最末结点的vis值。

    查询时,一旦路径上有一个vis值为0,就查询失败。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    struct Trie
    {
        int vis;
        int next[26];
    }tree[3000005];
    
    int q, top;
    
    void build()
    {
        top = 0;
        for (int i = 0; i < 26; ++i) tree[0].next[i] = -1;
        tree[0].vis = 0;
    }
    
    int createNode()
    {
        top++;
        for (int i = 0; i < 26; ++i) tree[top].next[i] = -1;
        tree[top].vis = 0;
        return top;
    }
    
    void add(char str[])
    {
        int len = strlen(str), k, now = 0;
        for (int i = 0; i < len; ++i)
        {
            k = str[i]-'a';
            if (tree[now].next[k] == -1) tree[now].next[k] = createNode();
            now = tree[now].next[k];
            tree[now].vis++;
        }
    }
    
    void del(char str[])
    {
        int len = strlen(str), k, now = 0, cnt;
        for (int i = 0; i < len; ++i)
        {
            k = str[i]-'a';
            if (tree[now].next[k] == -1) return;
            now = tree[now].next[k];
        }
        for (int i = 0; i < 26; ++i) tree[now].next[i] = -1;
        cnt = tree[now].vis;
        now = 0;
        for (int i = 0; i < len; ++i)
        {
            k = str[i]-'a';
            now = tree[now].next[k];
            tree[now].vis -= cnt;
        }
    }
    
    bool get(char str[])
    {
        int len = strlen(str), k, now = 0;
        for (int i = 0; i < len; ++i)
        {
            k = str[i]-'a';
            if (tree[now].next[k] == -1) return false;
            now = tree[now].next[k];
            if (!tree[now].vis) return false;
        }
        return true;
    }
    
    void work()
    {
        build();
        char op[20], str[40];
        for (int i = 0; i < q; ++i)
        {
            scanf("%s%s", op, str);
            switch (op[0])
            {
                case 'i':
                    add(str);
                    break;
                case 'd':
                    del(str);
                    break;
                case 's':
                    if (get(str)) printf("Yes
    ");
                    else printf("No
    ");
                    break;
            }
        }
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        //freopen("test.out", "w", stdout);
        while (scanf("%d", &q) != EOF)
            work();
        return 0;
    }
    View Code

    D题:

    这题直接排序+map能过。没试字典树。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        //freopen("test.out", "w", stdout);
        int n;
        char str[50];
        while (scanf("%d", &n) != EOF)
        {
            map<string, int> s;
            for (int i = 0; i < n; ++i)
            {
                scanf("%s", str);
                sort(str, str+strlen(str));
                printf("%d
    ", s[str]++);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    [置顶] win7 && win8 下安装SqlServer 2008出现错误无法将对象实例化的问题
    [置顶] sizeof()和c++中变量们
    [置顶] sql2008 附加数据库 .mdf 出现错误 解决方案
    [置顶] 漂亮的 tab 样式
    [置顶] 认识指针和指针变量
    [置顶] SqlHelper类
    [置顶] 第一次使用事物 利用线性表
    [置顶] 设计模式之单例模式 (Design patterns of the The singleton pattern)c#
    [置顶] ListBox控件的数据绑定
    RedHat 6.0(64位)如何使用CentOS YUM源更新的方法
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/5492848.html
Copyright © 2011-2022 走看看