CF1761D

考虑设 \(f(i)\) 表示从低到高第 \(i\) 位的进位情况,\(0\) 表示不进位,\(1\) 表示进位。

分类讨论一下:

  • \(f(i-1)=f(i)=1\),那么 \(a,b\) 这一位有三种情况 \((1,1),(1,0),(0,1)\)
  • \(f(i-1)=f(i)=0\),那么 \(a,b\) 这一位有三种情况 \((0,0),(1,0),(0,1)\)
  • \(f(i-1)=1,f(i)=0\),那么 \(a,b\) 这一位有一种情况 \((0,0)\)
  • \(f(i-1)=0,f(i)=1\),那么 \(a,b\) 这一位有一种情况 \((1,1)\)

于是发现 \(f(i)=f(i-1)\) 要乘 \(3\),否则不变。

设总共有 \(n+1\) 位,并强制 \(f(0)=0\)

枚举有 \(x\) 个位置满足 \(f(i)\ne f(i-1)\),那么总共有 \(x+1\)\(01\) 连续段,其中 \(0\) 的连续段有 $\left \lceil \dfrac{x+1}{2} \right \rceil $ 个,\(1\) 的连续段有 $\left \lfloor \dfrac{x+1}{2} \right \rfloor $ 个。

由于要填 \(k\)\(1\),所以要填 \(n+1-k\)\(0\)

而把 \(x\) 个元素分成 \(y\) 段的方案数,经典的隔板法,是 \(\dbinom{x-1}{y-1}\)

于是总的式子是

\[\sum_{i=1}^n 3^{n-i}\times \dbinom{(n+1-k)-1}{\left \lceil \dfrac{i+1}{2} \right \rceil -1}\times \dbinom{k-1}{\left \lfloor \dfrac{i+1}{2} \right \rfloor -1} \]

记得特判 \(k=0\) 的情况。

Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000005, mod = 1e9 + 7;
int n, k;
int fac[N], inv[N], pw[N];
int ans;

int qpow(int x, int y) {
	int res = 1;
	while (y) {
		if (y & 1) res = 1ll * res * x % mod;
		x = 1ll * x * x % mod;
		y >>= 1;
	}
	return res;
}

void init(int n) {
	fac[0] = pw[0] = 1;
	for (int i = 1; i <= n; ++i) fac[i] = 1ll * fac[i - 1] * i % mod, pw[i] = 1ll * pw[i - 1] * 3 % mod;
	inv[n] = qpow(fac[n], mod - 2);
	for (int i = n - 1; ~i; --i) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
}

int C(int n, int m) {
	if (n < 0 || m < 0 || n < m) return 0;
	return 1ll * fac[n] * inv[n - m] % mod * inv[m] % mod;
}

void add(int &a, int b) {
	a += b;
	if (a >= mod) a -= mod;
}

int main() {
	scanf("%d%d", &n, &k);
	init(n);
	if (!k) return printf("%d", pw[n]), 0;
	for (int i = 1; i <= n; ++i) add(ans, 1ll * pw[n - i] * C(n + 1 - k - 1, ((i + 1) - (i + 1) / 2) - 1) % mod * C(k - 1, (i + 1) / 2 - 1) % mod);
	printf("%d", ans);
	return 0;
}
posted @ 2022-11-25 10:16  Kobe303  阅读(17)  评论(0编辑  收藏  举报