[Codeforces 1045] Bubble Cup 11 - Finals [Online Mirror, Div. 1] -H Self-exploration

版权声明:欢迎转载蒟蒻博客,但请注明出处: https://blog.csdn.net/LPA20020220/article/details/86490743

洛谷传送门

Codeforces传送门

题目大意

求在 [ l , r ] [l,r] 区间内有多少数满足在二进制下:

  • 子串 00 00 的个数为 C 00 C00
  • 子串 01 01 的个数为 C 01 C01
  • 子串 10 10 的个数为 C 10 C10
  • 子串 11 11 的个数为 C 11 C11 。 答案对 1 0 9 + 7 10^9+7 取模。

l , r 2 100   000 \large l,r≤2^{100 \ 000}

输入输出格式

输入格式

第一行一个由 0 , 1 0,1 组成的字符串, 表示 l l

第二行一个由 0 , 1 0,1 组成的字符串, 表示 r r

以下四行, 每行一个整数, 表示 C 00 , C 01 , C 10 , C 11 C00,C01,C10,C11

输出格式

一行一个正整数, 表示满足要求的数的个数。

输入输出样例

输入样例#1:

10
1001
0
0
1
1

输出样例#1:

1

输入样例#2:

10
10001
1
2
3
4

输出样例#2:

0

解题分析

很显然的一个数位 d p dp 01 , 10 01,10 这两种只会交替出现, 其他的 00 , 01 00,01 插进去, 组合数算算就好了。

不过考试的时候脑袋被门夹了, 居然 d p dp 的时候直接带着上界下界就开始了… 显然可以两个前缀相减啊QAQ。

代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <cctype>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define File freopen("i.in", "r", stdin), freopen("i.out", "w", stdout)
#define MX 200500
#define ll long long
#define MOD 1000000007
char bf1[MX], bf2[MX];
int down[MX], up[MX], _debug[MX];
ll inv[MX], fac[MX];
int a, b, c, d, tot;
ll res;
bool all1;
void pre()
{
	inv[0] = inv[1] = fac[0] = fac[1] = 1;
	for (R int i = 2; i < MX; ++i)
	inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD, fac[i] = i * fac[i - 1] % MOD;;
	for (R int i = 2; i < MX; ++i) inv[i] = inv[i - 1] * inv[i] % MOD;
	int len1 = std::strlen(bf1 + 1), len2 = std::strlen(bf2 + 1);
	if (len1 < tot)
	{
		down[1] = 1;
		for (R int i = 2; i <= tot; ++i) down[i] = 0;
	}
	else if (len1 > tot) puts("0"), exit(0);
	else for (R int i = 1; i <= tot; ++i) down[i] = bf1[i] - '0';
	if (len2 < tot) puts("0"), exit(0);
	else if (len2 > tot) for (R int i = 1; i <= tot; ++i) up[i] = 1;
	else for (R int i = 1; i <= tot; ++i) up[i] = bf2[i] - '0';
	all1 = true;
	for (R int i = 1; i <= tot; ++i) if (!up[i]) all1 = false;
	for (R int i = 2; i <= tot; ++i) if (down[i]) all1 = false;
	for (R int i = 1; i <= tot; ++i)
	{
		if (up[i] > down[i]) break;
		if (up[i] < down[i]) puts("0"), exit(0);
	}
}
IN ll C(R int n, R int m)
{
	if (n == m) return 1;
	if (n < m) return 0;
	if (n >= 0 && m < 0) return 0;
	return fac[n] * inv[m] % MOD * inv[n - m] % MOD;
}
namespace BF
{
	IN bool check(R int v)
	{
		int p1, p2, p3, p4, h, l;
		p1 = p2 = p3 = p4 = 0;
		for (R int i = 1; i < tot; ++i)
		{
			l = (v >> (i - 1)) & 1;
			h = (v >> i) & 1;
			if (l == 0 && h == 0) p1++;
			else if (l == 1 && h == 0) p2++;
			else if (l == 0 && h == 1) p3++;
			else p4++;
		}
		if (p1 == a && p2 == b && p3 == c && p4 == d) return true;
		return false;
	}
	void solve1() // O(2 ^ len * len)
	{
		R int st = 0, ed = 0, ans = 0;
		for (R int i = 1; i <= tot; ++i) st = (st << 1) | down[i], ed = (ed << 1) | up[i];
		for (R int i = st; i <= ed; ++i) ans += check(i);
		printf("%d", ans);
	}
	void solve2() //O(1), for (10000 -> 11111)
	{
		if (b > c) return puts("0"), void();//10 < 01, GG
		int cnt0 = c, cnt1 = 1 + b;
		ll ans = C(a + cnt0 - 1, cnt0 - 1) * C(d + cnt1 - 1, cnt1 - 1) % MOD;
		printf("%lld\n", ans);
	}
	void calc(R int dgt, R int la, R int lb, R int lc, R int ld)
	{
		if (la < 0 || lb < 0 || lc < 0 || ld < 0) return;
		if (dgt) {if (lb > lc) return;}
		else if (lb < lc) return;
		if (std::abs(lb - lc) > 1) return;
		int cnt0 = lc, cnt1 = lb;
		if (dgt) ++cnt1; else ++cnt0;
		res = (res + C(la + cnt0 - 1, cnt0 - 1) * C(ld + cnt1 - 1, cnt1 - 1) % MOD) % MOD;
	}
	void DFS(R int now, R int dgt, R int la, R int lb, R int lc, R int ld, R bool kh, R bool kd)
	//kh : upper_bound is reached
	//kd : lower_bound is reached
	{
		_debug[now] = dgt;
		int nex = now + 1;
		if ((!kh) && (!kd))
		return calc(dgt, la, lb, lc, ld), void();
		if (now == tot) return res += ((la == 0) && (lb == 0) && (lc == 0) && (ld == 0)), void();
		if (kh && kd)//must be 01
		{
			if (up[nex] == down[nex])//the same, can't change the state
			{
				if (dgt == 0)
				{
					if (up[nex] == 0) DFS(nex, up[nex], la - 1, lb, lc, ld, kh, kd);
					else DFS(nex, up[nex], la, lb - 1, lc, ld, kh, kd);
				}
				else
				{
					if (up[nex] == 0) DFS(nex, up[nex], la, lb, lc - 1, ld, kh, kd);
					else DFS(nex, up[nex], la, lb, lc, ld - 1, kh, kd);
				}
			}
			else
			{
				if (dgt == 0)
				{
					DFS(nex, up[nex], la, lb - 1, lc, ld, kh, false);//01, no lower_bound
					DFS(nex, down[nex], la - 1, lb, lc, ld, false, kd);//00, no upper_bound
				}
				else
				{
					DFS(nex, up[nex], la, lb, lc, ld - 1, kh, false);//11, no lower_bound
					DFS(nex, down[nex], la, lb, lc - 1, ld, false, kd);//10, no upper_bound
				}
			}
		}
		else if (kh)//no deal with lower_bound
		{
			if (up[nex] == 0)
			{
				if (dgt == 0) DFS(nex, up[nex], la - 1, lb, lc, ld, kh, kd);//00
				else DFS(nex, up[nex], la, lb, lc - 1, ld, kh, kd);//10
			}
			else
			{
				if (dgt == 0)
				{
					DFS(nex, 0, la - 1, lb, lc, ld, false, kd);//00, no upper_bound
					DFS(nex, 1, la, lb - 1, lc, ld, kh, kd);//01, 
				}
				else
				{
					DFS(nex, 0, la, lb, lc - 1, ld, false, kd);//10, no upper_bound
					DFS(nex, 1, la, lb, lc, ld - 1, kh, kd);//11
				}
			}
		}
		else //no deal with upper_bound
		{
			if (down[nex] == 1)
			{
				if (dgt == 0) DFS(nex, down[nex], la, lb - 1, lc, ld, kh, kd);//01
				else DFS(nex, down[nex], la, lb, lc, ld - 1, kh, kd);//11
			}
			else
			{
				if (dgt == 0)
				{
					DFS(nex, 0, la - 1, lb, lc, ld, kh, kd);//00
					DFS(nex, 1, la, lb - 1, lc, ld, kh, false);//01, no lower_bound
				}
				else
				{
					DFS(nex, 0, la, lb, lc - 1, ld, kh, kd);//10
					DFS(nex, 1, la, lb, lc, ld - 1, kh, false);//11, no lower_bound	
				}
			}
		}
		
	}
}
int main(void)
{
	scanf("%s%s", bf1 + 1, bf2 + 1);
	scanf("%d%d%d%d", &a, &b, &c, &d);
	tot = a + b + c + d + 1;
	pre();
	//if (all1) BF::solve2();
	//else if (tot <= 25) BF::solve1();
	//else
	{
		BF::DFS(1, 1, a, b, c, d, 1, 1);
		printf("%lld\n", res);
	}
}

猜你喜欢

转载自blog.csdn.net/LPA20020220/article/details/86490743