(Solution)
对于答案,我们可以搞搞搞,最后搞出来一个:
[Ans = ∑_{i=0}^{a-1}C(i,a+b)=∑_{i=b+1}^{a+b}C(i,a+b)
]
所以我们可以发现:$$Ans = (2{a+b}+∑_{i=b+1}{a-1}C(i,a+b))/2$$
由于(a-b<=10000),所以我们可以暴力求出右边的东西。
现在的问题就是如何求(C(n,m)%10^10),我们可以用扩展lucas定理来搞。
具体看码吧。
(Code)
#include <cstdio>
#define N 100000
#define mo 10000000000ll
#define ll long long
#define mo2 1024
#define mo5 9765625
#define fo(x, a, b) for (int x = (a); x <= (b); x++)
using namespace std;
int h2[1000010], h5[1000010];
ll v2[1035], v5[9765636];
ll a, b, K, ans;
inline int read() {
int x = 0, f = 0; char c = getchar();
while (c < '0' || c > '9') f = (c == '-') ? 1 : f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
ll ksc(ll x, ll y, ll mm) {
ll s = 0;
while (y) {
if (y & 1) s = (s + x) % mm;
x = (x + x) % mm, y >>= 1;
}
return s;
}
ll ksm(ll x, ll y, ll mm) {
if (y == 0) return 1;
ll s = 1;
while (y) {
if (y & 1) s = ksc(s, x, mm);
x = ksc(x, x, mm), y >>= 1;
}
return s;
}
void prepare() {
h2[1] = 0; fo(i, 2, 1000000) h2[i] = h2[i / 2] + i / 2;
h5[1] = 0; fo(i, 2, 1000000) h5[i] = h5[i / 5] + i / 5;
v2[0] = v2[1] = v2[2] = 1;
fo(i, 3, mo2)
if (! (i & 1)) v2[i] = v2[i - 1];
else v2[i] = v2[i - 1] * i % mo2;
v5[0] = v5[1] = 1;
fo(i, 2, mo5)
if (i % 5 == 0) v5[i] = v5[i - 1];
else v5[i] = v5[i - 1] * i % mo5;
}
ll exgcd(ll a, ll b, ll &x, ll &y);
ll hav_2(ll x) {
if (x <= 1000000) return h2[x];
return hav_2(x / 2) + (x / 2);
}
ll get_2(ll x) {
if (x == 0) return 1;
ll s = ksm(v2[mo2 - 1], x / mo2, mo2) * v2[x % mo2] % mo2;
return get_2(x / 2) * s % mo2;
}
ll solve_2(ll x, ll y) {
ll s = 1, s1 = hav_2(y), s2 = hav_2(x) + hav_2(y - x);
if (s1 - s2 >= 10) return 0;
fo(i, 1, s1 - s2) s = s << 1;
s1 = get_2(y), s2 = get_2(x) * get_2(y - x) % mo2;
ll x_, y_; exgcd(s2, mo2, x_, y_); x_ = (x_ % mo2 + mo2) % mo2;
s = s * s1 % mo2 * x_ % mo2;
return s;
}
ll hav_5(ll x) {
if (x <= 1000000) return h5[x];
return hav_5(x / 5) + (x / 5);
}
ll get_5(ll x) {
if (x == 0) return 1;
ll s = ksm(v5[mo5 - 1], x / mo5, mo5) * v5[x % mo5] % mo5;
return get_5(x / 5) * s % mo5;
}
ll solve_5(ll x, ll y) {
ll s = 1, s1 = hav_5(y), s2 = hav_5(x) + hav_5(y - x);
if (s1 - s2 >= 10) return 0;
fo(i, 1, s1 - s2) s = s * 5;
s1 = get_5(y), s2 = get_5(x) * get_5(y - x) % mo5;
ll x_, y_; exgcd(s2, mo5, x_, y_); x_ = (x_ % mo5 + mo5) % mo5;
s = s * s1 % mo5 * x_ % mo5;
return s;
}
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (! b) {x = 1, y = 0; return a;}
ll t = exgcd(b, a % b, y, x);
y = y - a / b * x; return t;
}
ll C(ll x, ll y) {
ll s1 = solve_2(x, y), s2 = solve_5(x, y);
ll x_, y_; ll gd = exgcd(mo2, mo5, x_, y_);
x_ = x_ * (s2 - s1) / gd, y_ = y_ * (s2 - s1) / gd;
ll S = ((mo2 * x_ + s1) % mo + mo) % mo;
return S;
}
int main()
{
freopen("coin.in", "r", stdin);
freopen("coin.out", "w", stdout);
prepare();
while (scanf("%lld%lld%lld", &a, &b, &K) != EOF) {
ll mod = 1; fo(i, 1, K) mod = mod * 10;
ans = ksm(2, a + b - 1, (ll)mo2 * mo5);
if (a > b) {
if ((a - b + 1) % 2 == 0) {
ll le = b + 1, ri = (a + b - 1) / 2;
for (ll i = le; i <= ri; i++)
ans = (ans + C(i, a + b)) % mo;
}
else {
ans = (ans + C((a + b) / 2, a + b) / 2) % mo;
ll le = b + 1, ri = (a + b) / 2 - 1;
for (ll i = le; i <= ri; i++)
ans = (ans + C(i, a + b)) % mo;
}
}
else ans = (ans + mo - C((a + b) / 2, a + b) / 2) % mo;
ans = ans % mod;
switch (K) {
case 1:printf("%01lld
", (ll)ans); break;
case 2:printf("%02lld
", (ll)ans); break;
case 3:printf("%03lld
", (ll)ans); break;
case 4:printf("%04lld
", (ll)ans); break;
case 5:printf("%05lld
", (ll)ans); break;
case 6:printf("%06lld
", (ll)ans); break;
case 7:printf("%07lld
", (ll)ans); break;
case 8:printf("%08lld
", (ll)ans); break;
case 9:printf("%09lld
", (ll)ans); break;
}
}
return 0;
}