bzoj 4569: [Scoi2016] cute

Description

A large number of length n is represented by S1S2S3...Sn, where Si represents the ith bit of the number, S1 is the highest bit of the number, and tells you some restrictions, each
condition is represented as four numbers, l1, r1, l2, r2, ie, two intervals with the same length, indicate that the substrings Sl1Sl1+1Sl1+2...Sr1 are
exactly the same as Sl2Sl2+1Sl2+2...S r2. For example, when n=6, a certain restriction condition l1=1, r1=3, l2=4, r2=6, then 123123, 351351 satisfy the condition, but 12012, 13
1141 do not satisfy the condition, the length of the former number is not 6, The second position of the latter is different from the fifth position. Ask how many numbers meet all of the above conditions.

Solution

The brute force method is to combine the same, and the final answer is only related to the number of connected blocks.
For each limit, the complexity of the combination is \(O(n)\) We use the idea of
​​multiplication, which is \(st\ The idea of ​​) table If the \(k\)
th layer is merged , and \(find(i)==find(j)\) , it means \(S[i,i+2^k-1]=S[j ,j+2^k-1]\) also shows the \(k-1\) th layer, \(find(i)==find(j),find(i+1<<(k-1))= =find(j+(1<<(k-1)))\) By recursing layer by layer, we can get the union check set we require

#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;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325008907&siteId=291194637