luogu P3295 [SCOI2016]萌萌哒
傳送門
題目條件"兩個子串\(S[l_1,r_1],S[l_2,r_2]\)完全相同"等價(jià)于\(\forall i \in[0,r_1-l_1+1],S_{l1+i}=S_{l_2+i}\),然后所有相同位置的都要選一種數(shù)字,把所有相同的放在一個集合,然后記集合個數(shù)為\(cn\)那么答案就是\(9*10^{cn-1}\),因?yàn)榈谝晃徊粸?,然后就可以暴力并查集做到\(O(n^2)\)了
發(fā)現(xiàn)這樣的連邊是一個區(qū)間對應(yīng)向另一個區(qū)間連邊,可以考慮優(yōu)化.因?yàn)檫B邊要一一對應(yīng),所以可以ST表優(yōu)化連邊.就是每個點(diǎn)拆出\(log\)個點(diǎn),代表以這個點(diǎn)為左端點(diǎn)的長度為\(2^k\)的區(qū)間,然后每次兩個區(qū)間二進(jìn)制拆分一下,在對應(yīng)的點(diǎn)連邊就好了個鬼.不過這樣還是不對的,最后還要把這些連的邊的作用發(fā)揮出來,就從上往下遍歷ST表的每一層,某個點(diǎn)如果在當(dāng)前層的根不是自己,那么就把自己的左兒子,右兒子分別向根的兩個兒子連邊,然后做下去
#include<bits/stdc++.h> #define LL long long #define db long double #define il inline #define re registerusing namespace std; const int N=1e5+10,mod=1e9+7; il LL rd() {LL x=0,w=1;char ch=0;while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}return x*w; } int n,m,lz,ff[N][17],l2[N]; int findf(int x,int i){return ff[x][i]==x?x:ff[x][i]=findf(ff[x][i],i);} int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;}return an;}int main() {n=rd(),m=rd();lz=log2(n);for(int j=0;j<=lz;++j) l2[1<<j]=j;for(int j=0;j<=lz;++j)for(int i=1;i+(1<<j)-1<=n;++i)ff[i][j]=i;while(m--){int l=rd(),r=rd(),ll=rd(),rr=rd();if(l==ll) continue;rr=rr-ll+1;while(rr){int x=rr&(-rr),y=l2[x];ff[findf(l,y)][y]=findf(ll,y);l+=x,ll+=x;rr-=x;}}for(int j=lz;j;--j){for(int i=1;i+(1<<j)-1<=n;++i)if(i!=findf(i,j))ff[findf(i,j-1)][j-1]=findf(findf(i,j),j-1),ff[findf(i+(1<<(j-1)),j-1)][j-1]=findf(findf(i,j)+(1<<(j-1)),j-1);}int cn=0;for(int i=1;i<=n;++i) cn+=i==findf(i,0);printf("%lld\n",9ll*fpow(10,cn-1)%mod);return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/smyjr/p/10537890.html
總結(jié)
以上是生活随笔為你收集整理的luogu P3295 [SCOI2016]萌萌哒的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习笔记(29):Python网络编程并
- 下一篇: git 多用户多仓库配置