zoukankan      html  css  js  c++  java
  • 随机化的奇妙用法

    一、随机化避免碰撞

    1.对数字进行随机化后可以避免数字发生碰撞。

    例题:P2087 GTY的人类基因组计划2

    这道题的唯一难点是判断一个房间里的一群人是否出现过。

    可以考虑对于每一个人赋予他一个rand值,然后用rand值的和判断是否出现过。

    比如有编号1,2,3的三个人,假设他们的rand值为11,45,14

    1和2同时出现的时候他们的rand值之和sum_rand=56而他们的编号之和sum_pos=3

    发现sum_rand!=rand[3]但是sum_pos=pos[3]

    用rand有效的减小了碰撞的概率。

    那么这道题的思路就非常简单了。

    map<int, int> vis;
    set<int> s;
    int a[MAXN], to[MAXN], n, m, q, num[MAXN], h[MAXN];
    
    signed main()
    {
        srand(2004 + 8 + 21);
        n = read(), m = read(), q = read();
        for (int i = 1; i <= n; i++) 
        {
            a[i] = rand() * rand() % 1145141919 * (rand() * rand() % 19260817) * 810;
            h[1] ^= a[i];
            to[i] = 1;
            num[1]++;
        }
        s.insert(1);
        while (q--)
        {
            char opt;
            cin >> opt;
            int x = read(), y = read();
            if (opt == 'C')
            {
                if (to[x] == y) continue;
                s.erase(to[x]);
                s.erase(y);
                h[to[x]] ^= a[x];
                h[y] ^= a[x];
                num[to[x]]--;
                num[y]++;
                if (!vis[h[to[x]]]) s.insert(to[x]);
                if(!vis[h[y]]) s.insert(y);
                to[x] = y;
            }
            if (opt == 'W')
            {
                int ans = 0;
                auto it = s.lower_bound(x);
                for (; it != s.end() && *it <= y; it = s.lower_bound(x))
                {
                    vis[h[*it]] = 1;
                    ans += num[*it];
                    s.erase(it);
                }
                cout << ans;
                puts("");
            }
        }
        return 0;
    }
    View Code

    2.多次随机化避免碰撞

    例题: P2312 解方程

    直接算会溢出,可以随机取几个模数,

    对于一个数x如果取模后计算出来的方程结果是0,那么这个x就是一个答案。

    int n, m, a[MAXN], k[MAXN], cnt, t, ans, sum;
    
    int calc(int x, int MOD)
    {
        sum = 0;
        for (int i = n; i >= 1; i--)
        {
            sum = ((sum + a[i]) * x) % MOD;
        }
        sum = (sum + a[0]) % MOD;
        return !sum;
    }
    
    signed main()
    {
        n = read(), m = read();
        for (int i = 0; i <= n; i++)
        {
            a[i] = read();
        }
        for (int i = 1; i <= m; i++)
        {
            if (calc(i,rand())&&calc(i,rand()))
            {
                t = 1;
                ans++;
                k[++cnt] = i;
            }
        }
        if (!t)
        {
            puts("0");
            return 0;
        }
        printf("%lld", ans);
        puts("");
        for (int i = 1; i <= cnt; i++)
        {
            printf("%lld", k[i]);
            puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    LeetCode Binary Tree Inorder Traversal
    LeetCode Populating Next Right Pointers in Each Node
    LeetCode Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode Reverse Linked List II
    LeetCode Populating Next Right Pointers in Each Node II
    LeetCode Pascal's Triangle
    Palindrome Construct Binary Tree from Preorder and Inorder Traversal
    Pascal's Triangle II
    LeetCode Word Ladder
    LeetCode Binary Tree Zigzag Level Order Traversal
  • 原文地址:https://www.cnblogs.com/dead-gun/p/12945719.html
Copyright © 2011-2022 走看看