Description
Link.
给定一个长度为 (n) 的数组让你填数,需要满足 (m) 个形如 (([l_{1},r_{1}],[l_{2},r_{2}])) 的要求,这两个区间填好后需要一样,问方案数。
Solution
Let us only consider one limit (([l_{1},r_{1}],[l_{2},r_{2}])), the number of ways is (10^{r-l+1}).
Connecting every (iin[l_{1},r_{1}]) and (jin[l_{2},r_{2}]), we can construct a graph.
Counting the number of connected subgraphs, denoted as (x), the answer is (9 imes10^{x-1}), and the complexity is (mathcal{O}(n^{2}alpha(n))).
Each interval could be splited into (log_{2}r-l+1) subintervals, so that we can solve this in (mathcal{O}(nlog_{2}nalpha(n))).
#include <bits/stdc++.h>
typedef long long ll;
#define sf(x) scanf("%d",&x)
#define ssf(x) scanf("%lld",&x)
struct DSU {
int fa[100010];
void init(int l) {
std::iota(fa + 1, fa + l + 1, 1);
}
int find(int x) {
return (x ^ fa[x]) ? fa[x] = find(fa[x]) : x;
}
void ins(int x, int y) {
if (x ^ y)
fa[x] = y;
}
} dsu[20];
int n, m, opl0, opr0, opl1, opr1;
ll ans = 1;
int main() {
sf(n), sf(m);
for (int i = 0; i ^ 20; ++i)
dsu[i].init(n);
while (m-- > 0) {
sf(opl0), sf(opr0), sf(opl1), sf(opr1);
int cur0 = opl0, cur1 = opl1;
for (int i = 19; ~i; --i) {
if (cur0 + (1 << i) - 1 <= opr0) {
dsu[i].ins(dsu[i].find(cur0), dsu[i].find(cur1));
cur0 += (1 << i);
cur1 += (1 << i);
}
}
}
for (int j = 19; j; --j) {
for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
dsu[j - 1].ins(dsu[j - 1].find(i), dsu[j - 1].find(dsu[j].find(i)));
dsu[j - 1].ins(dsu[j - 1].find(i + (1 << (j - 1))), dsu[j - 1].find(dsu[j].find(i) + (1 << (j - 1))));
}
}
for (int i = 1; i <= n; ++i)
if (dsu[0].fa[i] == i)
ans = ans * (ans == 1 ? 9 : 10) % 1000000007;
printf("%lld
", ans);
return 0;
}