• luogu P3295 [SCOI2016]萌萌哒 |倍增+并查集


    题目描述

    一个长度为 nnn 的大数,用 S1S2S3⋯SnS_1S_2S_3 cdots S_nS1​S2​S3​⋯Sn​表示,其中 SiS_iSi​ 表示数的第 iii 位, S1S_1S1​ 是数的最高位。告诉你一些限制条件,每个条件表示为四个数,l1,r1,l2,r2l_1,r_1,l_2,r_2l1​,r1​,l2​,r2​,即两个长度相同的区间,表示子串Sl1Sl1+1Sl1+2⋯Sr1S_{l_1}S_{l_1+1}S_{l_1+2} cdots S_{r_1}Sl1​​Sl1​+1​Sl1​+2​⋯Sr1​​与Sl2Sl2+1Sl2+2⋯Sr2S_{l_2}S_{l_2+1}S_{l_2+2} cdots S_{r_2}Sl2​​Sl2​+1​Sl2​+2​⋯Sr2​​完全相同。

    比如 n=6n=6n=6 时,某限制条件 l1=1,r1=3,l2=4,r2=6l_1=1,r_1=3,l_2=4,r_2=6l1​=1,r1​=3,l2​=4,r2​=6 ,那么 123123123123123123,351351351351351351 均满足条件,但是 120121201212012,131141131141131141 不满足条件,前者数的长度不为 666 ,后者第二位与第五位不同。问满足以上所有条件的数有多少个。

    输入格式

    第一行两个数n和m,分别表示大数的长度,以及限制条件的个数。

    接下来m行,对于第i行,有4个数 li1,ri1,li2,ri2,分别表示该限制条件对应的两个区间。

    1≤n≤1051le nle 10^51≤n≤105,1≤m≤1051le mle 10^51≤m≤105 ,1≤li1,ri1,li2,ri2≤n 1le li1,ri1,li2,ri2 le n 1≤li1,ri1,li2,ri2≤n ;并且保证 ri1−li1=ri2−li2 ri1-li1=ri2-li2 ri1−li1=ri2−li2 。

    输出格式

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


    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int _=1e5+10,N=16,p=1e9+7,mod=1e9+7;
    #define int long long
    int n,m,f[22][_];
    int get(int x,int y){
        return f[y][x]==x?x:f[y][x]=get(f[y][x],y);
    }
    bool vis[_];
    inline int ksm(int x,int y){
        int res=1;
        while(y){
            if(y&1)res=res*x%mod; 
            x=x*x%mod; y>>=1;
        }
        return res;
    }
    void merge(int x,int y,int len){
      if(get(x,len)!=get(y,len))
        f[len][f[len][x]]=f[len][y];
    }
    signed main(){
        cin>>n>>m;
        for(int j=0;j<=21;j++)for(int i=1;i<=n;i++)f[j][i]=i;
        int l1,l2,r1,r2;
        for(int i=1;i<=m;i++){
            scanf("%lld%lld%lld%lld",&l1,&r1,&l2,&r2);
            for(int j=20;j>=0;j--)
            if(l1+(1<<j)-1<=r1)merge(l1,l2,j),l1+=1<<j,l2+=1<<j;
        }
        int ans=9,cnt=0;
        for(int j=20;j;j--)
        for(int i=1;i+(1<<j)-1<=n;i++)
        {merge(i,get(i,j),j-1);merge(i+(1<<(j-1)),f[j][i]+(1<<(j-1)),j-1);}
        for(int i=1;i<=n;i++)if(get(i,0)==i)cnt++;
        for(int i=1;i<cnt;i++)ans*=10,ans%=mod;
        cout<<ans<<endl;
    }
    
  • 相关阅读:
    IntelliJ IDEA教程之如何clean或者install Maven项目
    mysql 导出表,导出数据 命令
    import require
    https确实加密了。 抓包是一个中间人攻击过程
    密码学部分算法
    账号密码加密的方案
    查看git提交细节
    使用源安装java JDK
    updated stream stash changes
    Hibernate与Jpa的关系
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/12194446.html
Copyright © 2020-2023  润新知