時間限制: 1 sec 記憶體限制: 256 mb
提交: 12 解決: 2
[提交][狀態][討論版]
乙個長度為 n 的大數,用 s1s2s3...sn表示,其中 si表示數的第 i 位, s1是數的最高位,告訴你一些限制條件,每個條件表示為四個數,l1, r1, l2, r2,即兩個長度相同的區間,表示子串 sl1sl1+1sl1+2...sr1與 sl2sl2+1sl2+2...sr2完全相同。
比如 n = 6 時,某限制條件 l1= 1, r1= 3, l2 = 4, r2 = 6,那麼 123123, 351351 均滿足條件,但是 12012, 131141不滿足條件,前者數的長度不為 6,後者第二位與第五位不同。
問滿足以上所有條件的數有多少個
第一行兩個數 n 和 m,分別表示大數的長度,以及限制條件的個數
接下來 m 行,對於第 i 行, 有 4 個數 li1, ri1, li2, ri2,分別表示該限制條件對應的兩個區間
乙個數,表示滿足所有條件且長度為 n 的大數的個數,答案可能很大,因此輸出答案模 109+7 的結果即可
4 21 2 3 4
3 3 3 3
90100% 的資料,1 ≤ n ≤ 105, 1 ≤ m ≤ 105, 1 ≤ li1, ri1, li2, ri2≤ n,並且保證 ri1− li1= ri2− li2
【分析】暴力並查集合並肯定超時,考慮倍增的思想,將並查集分層,fa[k][x]表示從x開始的長度為2^k的合併,然後 高位到低位合併即可。
#include #define inf 0x3f3f3f3f#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
using
namespace
std;
typedef
long
long
ll;const
int n = 1e6+5500
;;const
int m = 160009
;const
int mod = 1e9+7
;const
double pi= acos(-1.0
);typedef pair
pii;
intn,m,t;
int up[n],go[n],fa[20
][n];
int findfa(int k,int
x)void unionfa(int k,int x,int
y)int
main()
int k=log2(r1-l1+1
); unionfa(k,l1,l2);unionfa(k,r1-(1
<1,r2-(1
<1
); }
int cnt=0
; ll ans=9
;
for(int i=1;i<=n;i++)
for(int i=0;i1;i++)
if(n==1)puts("10"
);
else printf("
%lld\n
",ans);
return0;
}
BZOJ 4569 萌萌噠 (並查集)
time limit 10 sec memory limit 256 mb description 乙個長度為n的大數,用s1 s2 s3 sn表示,其中si表示數的第i位,s1是數的最高位,告訴你一些限制條件,每個條 件表示為四個數,l1,r1,l2,r2,即兩個長度相同的區間,表示子串sl1 s...
BZOJ4569 萌萌噠 倍增 並查集
沒想到這兩個東西還可以這麼用,我們可以用f i j 表示 i i 2 j 1 這一段區間屬於哪乙個集合,沒有則等於0.那麼每次合併我們可以把這個限制拆成log個區間,依次合併起來。若f i j 和f s t 同屬乙個集合,那麼f i j 1 和f s t 1 f i 2j 1 j 1 和f s 2t...
SCOI2016 萌萌噠 並查集 倍增
傳送門 一開始是想賭一把,把節點乙個乙個的unite,然後懷著wa的心情wa了。然後又準備用離散去優化,然後又懷著wa的心情wa了。萬般無奈去查題解,發現竟然要使用倍增?倍增是啥,我多少年沒有用過了 複習了一波倍增,原來倍增也可以用在並查集上,我對並查集又有了新的理解,這個資料結構,好強啊!incl...