bzoj 4569: [Scoi2016]萌萌噠
阿新 • • 發佈:2018-04-27
stdin etc 有關 bits con clu include CP freopen
對於每一個限制,合並的復雜度是 \(O(n)\) 的
我們用倍增的思想,也就是 \(st\) 表的思想
假如在合並第 \(k\) 層,且 \(find(i)==find(j)\),說明 \(S[i,i+2^k-1]=S[j,j+2^k-1]\)
也說明第 \(k-1\) 層,\(find(i)==find(j),find(i+1<<(k-1))==find(j+(1<<(k-1)))\)
逐層遞推下去就可以得到我們要求的並查集了
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,後者第二位與第五位不同。問滿足以上所有條件的數有多少個。
Solution
暴力做法就是把相同的合並在一起,最後答案只跟連通塊數量有關了
我們用倍增的思想,也就是 \(st\) 表的思想
假如在合並第 \(k\) 層,且 \(find(i)==find(j)\),說明 \(S[i,i+2^k-1]=S[j,j+2^k-1]\)
也說明第 \(k-1\) 層,\(find(i)==find(j),find(i+1<<(k-1))==find(j+(1<<(k-1)))\)
逐層遞推下去就可以得到我們要求的並查集了
#include<bits/stdc++.h>
using namespace std;
template<class T>void gi(T &x){
int f;char c;
for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
}
const int N=1e5+10,mod=1e9+7;
int n,m,Log[N];
struct ST{
int fa[N];
inline void init(){for(int i=1;i<=n;i++)fa[i]=i;}
inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
inline void merge(int x,int y){fa[find(y)]=find(x);}
}st[25];
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>n>>m;
int l1,l2,r1,r2,len;
for(int i=2;i<=n;i++)Log[i]=Log[i>>1]+1;
for(int i=0;i<=Log[n];i++)st[i].init();
for(int i=1;i<=m;i++){
gi(l1);gi(r1);gi(l2);gi(r2);len=Log[r1-l1+1];
st[len].merge(l1,l2);st[len].merge(r1-(1<<len)+1,r2-(1<<len)+1);
}
for(int j=Log[n];j>=1;j--)
for(int i=1;i+(1<<j)-1<=n;i++){
int k=st[j].find(i);
if(i==k)continue;
st[j-1].merge(i,k);
st[j-1].merge(i+(1<<(j-1)),k+(1<<(j-1)));
}
int cnt=0;
for(int i=1;i<=n;i++)if(st[0].find(i)==i)cnt++;
int ans=9;
for(int i=1;i<cnt;i++)ans=1ll*ans*10%mod;
cout<<ans<<endl;
return 0;
}
bzoj 4569: [Scoi2016]萌萌噠