1. 程式人生 > >Codeforces 935D Fafa and Ancient Alphabet

Codeforces 935D Fafa and Ancient Alphabet

class 兩個 clu esp ble 高位到低位 mar blog --

題目鏈接

題意

給定兩個\(n\)位的\(m\)進制數\(s1,s2\),所有出現的\(0\)均可等概率地被其他數字替換,求\(s1\gt s2\)的概率。

思路

從高位到低位,根據每一位上相應的\(0\)的個數進行 分類討論

計算每一位的時候加上這樣一部分答案:比到該位恰能比出大小的情況數。

恰能比出大小意味著:高位全部相同,該位\(s1\gt s2\),低位隨便怎麽取。

因此,需對兩個數目進行記錄:1. 前面有多少位是兩者皆0;2. 後面還有多少個0沒有確定。

另:\(x\)關於\(mod\)的乘法逆元為\(x^{(mod-2)}\),由費馬小定理易得。

註意:要對\(m\)的冪次進行預處理。

Code

#include <bits/stdc++.h>
#define maxn 100010
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
typedef long
long LL; const LL mod = 1e9+7; int a[maxn], b[maxn]; LL rec[maxn*2]; LL poww(LL a, LL b) { LL ret = 1; while (b) { if (b&1) (ret *= a) %= mod; (a *= a) %= mod; b >>= 1; } return ret; } LL f(LL p, LL q) { return p * poww(q, mod-2) % mod; } LL GCD(LL a, LL b) { return
b ? GCD(b, a%b) : a; } int main() { int n, m; scanf("%d%d", &n, &m); LL NUM = (1LL*m*m%mod-m+mod)%mod * poww(2, mod-2) % mod; int tot=0; F(i, 0, n) { scanf("%d", &a[i]); if (!a[i]) ++tot; } F(i, 0, n) { scanf("%d", &b[i]); if (!b[i]) ++tot; } rec[0] = 1; F2(i, 1, tot) rec[i] = rec[i-1]*m%mod; LL q = poww(m, tot), p=0; int cnt=0, prev=0; F(i, 0, n) { if (a[i]&&b[i]) { if (a[i]>b[i]) (p += rec[cnt+tot-prev]) %= mod; if (a[i]!=b[i]) { printf("%I64d\n", f(p, q)); return 0; } } else if (!a[i] && !b[i]) { prev += 2; (p += (rec[cnt+tot-prev] * NUM % mod)) %= mod; ++cnt; } else { ++prev; if (a[i]) (p += rec[cnt+tot-prev] * (a[i]-1) % mod) %= mod; else (p += (rec[cnt+tot-prev] * (m-b[i]) % mod)) %= mod; } } LL gcd = GCD(p, q); p /= gcd, q /= gcd; printf("%I64d\n", f(p, q)); return 0; }

Codeforces 935D Fafa and Ancient Alphabet