1 条题解

  • 0
    @ 2026-5-2 16:57:05

    给每一列赋予两种属性:

    1. 会不会往下一位进位:ai=[xi+yi10]a_i = [x_i + y_i \ge 10]
    2. 需不需要上一位进位:$b_i = \left[x_i + y_i + 1 \equiv z_i \pmod {10}\right]$。

    发现 aia_i 的表述还不是很完备,修改为 ai=[xi+yi+bi10]a_i = [x_i + y_i + b_i \ge 10]

    所有列转化为 00,01,10,11\texttt{00},\texttt{01}, \texttt{10},\texttt{11} 的形式。

    我们发现一旦一个数的第二位为 11,其右边与之相邻的必然满足第一位为 11

    同理如果一个数的第一位为 11,其左边与之相邻的必然满足第二位为 11

    最后的答案一定形如 $\texttt{00}\ \texttt{01}\ \texttt{11}\cdots\texttt{11}\ \texttt{10} \ \texttt{00}\cdots$,即:

    1. 01\texttt{01}10\texttt{10} 数量相等,且两两配对。
    2. 11\text{11} 只能加在一对 0110\texttt{01}\cdots\texttt{10} 中间。
    3. 00\text{00} 只能加在开头,结尾,或一对 1001\texttt{10}\cdots\texttt{01} 当中。

    到此步为止,已经容易计数不考虑前导零的方案数了。

    考虑容斥,钦定开头是 00\texttt{00}01\texttt{01},满足 x=0y=0z=0x = 0\lor y = 0\lor z = 0,剩下的部分也容易计数。

    #include<bits/stdc++.h>
    #define eb emplace_back
    #define ep emplace
    using namespace std;
    
    using ll = long long;
    constexpr int N = 4e5 + 5, mod = 1e9 + 7;
    
    int n, cnt[2][2][2];
    char a[N], b[N], c[N];
    
    ll fac[N], inv[N];
    
    int s(int i, int j) {
    	return cnt[i][j][0] + cnt[i][j][1];
    }
    ll qpow(ll a, int b = mod - 2) {
    	ll c = 1;
    	while(b) {
    		if(b & 1) c = c * a % mod;
    		b >>= 1;
    		a = a * a % mod;
    	}
    	return c;
    }
    ll up(int i, int k) {
    	return fac[i + k - 1] * inv[i - 1] % mod;
    }
    ll C(int i, int j) {
    	if(j < 0) return 1;
    	return fac[i] * inv[j] % mod * inv[i - j] % mod;
    }
    int main() {
    	scanf("%s%s%s", a + 1, b + 1, c + 1);
    	n = strlen(a + 1);
    	for(int i = 1; i <= n; ++ i) {
    		int x = a[i] - '0', y = b[i] - '0', z = c[i] - '0';
    		int o = 0;
    		if((x + y + 1) % 10 == z) o = 1;
    		else if((x + y) % 10 != z) return cout << 0, 0;
    		++ cnt[x + y + o >= 10][o][x && y && z];
    	}
    	if(s(0, 1) != s(1, 0) || s(1, 1) && !s(0, 1)) {
    		return cout << 0, 0;
    	}
    	fac[0] = 1;
    	for(int i = 1; i <= 2 * n; ++ i) fac[i] = i * fac[i - 1] % mod;
    	inv[2 * n] = qpow(fac[2 * n]);
    	for(int i = 2 * n; i >= 1; -- i) inv[i - 1] = inv[i] * i % mod;
    	ll ans = fac[s(0, 1)] * fac[s(0, 1)] % mod;
    	ll coef = C(s(1, 1) + s(0, 1) - 1, s(0, 1) - 1) * fac[s(1, 1)] % mod;
    	ans = ans * coef % mod;
    	ll tmp = ans;
    	ans = ans * up(s(0, 1) + 1, s(0, 0)) % mod;
    	/*
    	  减去前导0
    	 */
    	ans = (ans + mod - tmp * cnt[0][0][0] % mod * up(s(0, 1) + 1, s(0, 0) - 1) % mod) % mod;
    	tmp = fac[s(1, 0)] * fac[s(0, 1) - 1] % mod * cnt[0][1][0] % mod;
    	tmp = tmp * coef % mod * up(s(0, 1), s(0, 0)) % mod;
    	cout << (ans + mod - tmp) % mod;
    	return 0;
    }
    
    • 1

    信息

    ID
    10283
    时间
    1000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者