4569: [Scoi2016]萌萌哒
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 482 Solved: 220
[ Submit][ Status][ Discuss]
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,后者第二位与第五位不同。问满足以上所有条件的数有多少个。
Input
第一行两个数n和m,分别表示大数的长度,以及限制条件的个数。接下来m行,对于第i行,有4个数li1,ri1,li2
,ri2,分别表示该限制条件对应的两个区间。
1≤n≤10^5,1≤m≤10^5,1≤li1,ri1,li2,ri2≤n;并且保证ri1-li1=ri2-li2。
Output
一个数,表示满足所有条件且长度为n的大数的个数,答案可能很大,因此输出答案模10^9+7的结果即可。
Sample Input
4 2
1 2 3 4
3 3 3 3
1 2 3 4
3 3 3 3
Sample Output
90
HINT
Source
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 1E5 + 10;
const int mo = 1E9 + 7;
int n,m,f[maxn][20];
int fa(int i,int j) {return f[i][j] == i?i:f[i][j] = fa(f[i][j],j);}
void Merge(int x,int y,int k)
{
int fx = fa(x,k),fy = fa(y,k);
if (fx == fy) return;
f[fx][k] = fy; if (!k) return;
Merge(x,y,k-1);
Merge(x+(1<<(k-1)),y+(1<<(k-1)),k-1);
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n >> m;
if (n == 1) {cout << 10; return 0;}
for (int i = 1; i <= n; i++)
for (int j = 0; j < 20; j++)
f[i][j] = i;
while (m--) {
int L1,R1,L2,R2;
scanf("%d%d%d%d",&L1,&R1,&L2,&R2);
if (L1 == L2) continue;
for (int j = 19; j >= 0; j--)
if (R1 - L1 + 1 >= (1<<j)) {
Merge(L1,L2,j);
L1 += (1<<j); L2 += (1<<j);
if (L1 > R1) break;
}
}
int tot = 0;
for (int i = 1; i <= n; i++)
if (fa(i,0) == i) ++tot;
int ans = 9;
for (int i = 1; i < tot; i++) ans = 10LL*ans%mo;
cout << ans;
return 0;
}