zoukankan      html  css  js  c++  java
  • bzoj 4569: [Scoi2016]萌萌哒

    4569: [Scoi2016]萌萌哒

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1199  Solved: 578
    [Submit][Status][Discuss]

    Description

    一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条
    件表示为四个数,l1,r1,l2,r2,即两个长度相同的区间,表示子串Sl1Sl1+1Sl1+2...Sr1与Sl2Sl2+1Sl2+2...S
    r2完全相同。比如n=6时,某限制条件l1=1,r1=3,l2=4,r2=6,那么123123,351351均满足条件,但是12012,13
    1141不满足条件,前者数的长度不为6,后者第二位与第五位不同。问满足以上所有条件的数有多少个。
     

    Input

    第一行两个数n和m,分别表示大数的长度,以及限制条件的个数。接下来m行,对于第i行,有4个数li1,ri1,li2
    ,ri2,分别表示该限制条件对应的两个区间。
    1≤n≤10^5,1≤m≤10^5,1≤li1,ri1,li2,ri2≤n;并且保证ri1-li1=ri2-li2。
     

    Output

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

     

    Sample Input

    4 2
    1 2 3 4
    3 3 3 3

    Sample Output

    90
    /*
        根据序列最大能承受的2^d得到d个st表
        st表套并查集,对于每一个规定,将两区间的左端点合并,再将右端点向左最多能移动的2^d到的位置进行合并(不知道怎么表达了)
        进行完一系列操作后,合并所有st表,最后进行统计即可 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 100010
    #define mod 1000000007
    using namespace std;
    int n,m,bin[maxn];
    struct node{
        int fa[maxn];
        void init(){for(int i=1;i<=n;i++)fa[i]=i;}
        int find(int x){
            if(fa[x]==x)return x;
            return fa[x]=find(fa[x]);
        }
        int merge(int x,int y){
            int f1=find(x),f2=find(y);
            if(f1!=f2)fa[f1]=f2;
        }
    }st[20];
    int mul(int x,int y){int res=1LL*x*y%mod;return res;}
    int Pow(int x,int y){
        int res=1;
        while(y){
            if(y&1)res=mul(res,x)%mod;
            x=mul(x,x)%mod;
            y>>=1;
        }
        return res;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=2;i<=n;i++)bin[i]=bin[i>>1]+1;
        for(int i=0;i<=bin[n];i++)st[i].init();
        int x,y,l,r;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&x,&y,&l,&r);
            int len=r-l+1,d=bin[len];
            st[d].merge(x,l);st[d].merge(y-(1<<d)+1,r-(1<<d)+1);
        }
        for(int j=bin[n];j;j--)//合并所有st表 
            for(int i=1;i+(1<<j)-1<=n;i++){
                int p=st[j].find(i);
                st[j-1].merge(i,p);
                st[j-1].merge(i+(1<<(j-1)),p+(1<<(j-1)));
            }
        int cnt=0;
        for(int i=1;i<=n;i++)cnt+=(st[0].find(i)==i);
        int ans=mul(9,Pow(10,cnt-1));//没有前导零 
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    LintCode "Maximum Gap"
    LintCode "Wood Cut"
    LintCode "Expression Evaluation"
    LintCode "Find Peak Element II"
    LintCode "Remove Node in Binary Search Tree"
    LintCode "Delete Digits"
    LintCode "Binary Representation"
    LeetCode "Game of Life"
    LintCode "Coins in a Line"
    LintCode "Word Break"
  • 原文地址:https://www.cnblogs.com/thmyl/p/8268508.html
Copyright © 2011-2022 走看看