zoukankan      html  css  js  c++  java
  • P3295 萌萌哒 题解

    题目

    一个长度为n的大数,用(S_1,S_2,S_3...S_n)表示,其中(S_i)表示数的第(i)位,(S_1)是数的最高位,告诉你一些限制条件,每个条
    件表示为四个数,(l_1,r_1,l_2,r_2),即两个长度相同的区间,表示子串(S_{l_1},S_{l_1+1},S_{l_1+2}...S_{r_1})(S_{l_2},S_{l_2+1},S_{l_2+2}...S_{r2})完全相同。比如(n=6)时,某限制条件(l_1=1,r_1=3,l_2=4,r_2=6),那么(123123)(351351)均满足条件,但是(12012)(131141)不满足条件,前者数的长度不为6,后者第二位与第五位不同。问满足以上所有条件的数有多少个。

    输入格式

    第一行两个数(n)(m),分别表示大数的长度,以及限制条件的个数。接下来(m)行,对于第(i)行,有4个数(l_{i_1},r_{i_1},l_{i_2},r_{i_2}),分别表示该限制条件对应的两个区间。

    (1≤n≤10^5,1≤m≤10^5,1≤l_{i_1},r_{i_1},l_{i_2},r_{i_2}≤n)并且保证(r_{i_1}-l_{i_1}=r_{i_2}-l_{i_2})

    输出格式

    一个数,表示满足所有条件且长度为n的大数的个数,答案可能很大,因此输出答案模 (10^9+7)的结果即可。

    输入样例

    4 2
    1 2 3 4
    3 3 3 3
    

    输出样例

    90
    

    题解

    这道题使用并查集和ST表

    (f)(ST)表数组, (f_{i,j})表示([i,i+2^j-1])

    一个条件可以拆成(log)份,然后再合并。

    (f_{s,t})(f_{i,j})在同一集合,则(f_{s,t-1})(f_{i,j-1})以及(f_{s+2^{t-1}-1,t-1})(f_{i+2^{j-1}-1,j-1})都在同一集合。

    为了满足条件,一层一层的做,把下一层的合并,编号大的合进编号小。

    (tot)为集合个数

    答案就是(9*10^{tot-1})

    代码

    #include <cmath>
    #include <cstdio>
    using namespace std;
    int n, m, fa[100005][18], ans;
    int find(int x, int k) { return fa[x][k] == x ? x : fa[x][k] = find(fa[x][k], k); }
    void join(int x, int y, int k) { if ((x = find(x, k)) != (y = find(y, k))) fa[x][k] = y; }
    int main() {
        scanf("%d %d", &n, &m);
        int maxk = floor(log2(n));
        for (int i = 1; i <= n; ++i)
            for (int k = 0; k <= maxk; ++k) fa[i][k] = i;
        for (int i = 1, l1, r1, l2, r2; i <= m; ++i) {
            scanf("%d %d %d %d", &l1, &r1, &l2, &r2);
            for (int k = maxk; ~k; --k)
                if (l1 + (1 << k) - 1 <= r1)
                    join(l1, l2, k), l1 += 1 << k, l2 += 1 << k;
        }
        for (int k = maxk; k; --k)
            for (int i = 1; i + (1 << k) - 1 <= n; ++i) {
                int pos = find(i, k);
                join(i, pos, k - 1);
                join(i + (1 << k - 1), pos + (1 << k - 1), k - 1);
            }
        for (int i = 1; i <= n; ++i)
            if (fa[i][0] == i) ans = !ans ? 9 : ans * 10ll % 1000000007;
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    JeePlus:代码生成器
    JeePlus:API工具
    Java实现 洛谷 P1023 税收与补贴问题
    Java实现 洛谷 P1023 税收与补贴问题
    Java实现 洛谷 P1023 税收与补贴问题
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
  • 原文地址:https://www.cnblogs.com/youxam/p/p3295.html
Copyright © 2011-2022 走看看