萌萌哒scoi2016

 

[萌萌哒](https://www.luogu.org/problem/P3295)

1.我们假设每次l1=r1,l2=r1;

即每次得到两个数相同的条件

最后通过并查集,我们可以得到x个块,方案数 9*(10ˆ(x-1));

然后,想一想st表,通过合并 每一层的块,并且在最后释放高层合并,将每个数合并到对应集合里

#include<bits/stdc++.h>
#define re return
#define dec(i,l,r) for(int i=l;i>=r;--i)
#define inc(i,l,r) for(int i=l;i<=r;++i)

using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x; 
}

int n,m,mod=1000000007;
int fa[100005][21],id[100005][21];

inline int find(int x,int k)
{
    re fa[x][k]==x?x:fa[x][k]=find(fa[x][k],k);
}
inline void merge(int x,int y,int k)
{
    int f1=find(fa[x][k],k);
    int f2=find(fa[y][k],k);
    fa[f2][k]=f1;
}
int main()
{
    rd(n);rd(m);
    
    if(n==1)
    {
        printf("0");
        re 0;
    }
    for(int j=0;(1<<j)<=n;++j)
    for(int i=1;i<=n-(1<<j)+1;++i)
    fa[i][j]=i;
    
    
    int l1,l2,r1,r2;
    inc(i,1,m)
    {
        rd(l1),rd(r1),rd(l2),rd(r2);
        dec(j,20,0)
        if(l1+(1<<j)-1<=r1)
        {
            merge(l1,l2,j);
            l1+=(1<<j);l2+=(1<<j);
        }
    }
    
    for(int j=log2(n);j>=1;--j)
    for(int i=1;i<=n-(1<<j)+1;++i)
    {
        int t=find(fa[i][j],j);
        if(t==i)continue;
        merge(i,t,j-1);
        merge(i+(1<<(j-1)),t+(1<<(j-1)),j-1);
    }
    
    
    long long ans=9,ret=n,a=10;
    inc(i,1,n)
    if(find(fa[i][0],0)!=i)
    --ret;
    
    --ret;
    while(ret)
    {
        if(ret&1)ans=(ans*a)%mod;
        a=(a*a)%mod; 
        ret>>=1;
    }
    printf("%lld",ans);
    re 0;
} 

 

posted @ 2019-08-14 14:36  凉如水  阅读(129)  评论(0编辑  收藏  举报