比較有意思...
經典的組合數取模問題,我們用質因數分解解決。
低位的計算就不說了,直接快速冪取模就可以。
對於高位的計算,我們計算log10下的答案,即log10(p1^a1*p2^a2*...*pk^ak) = a1*log10(p1) + a2*log10(p2) + ... + ak*log10(pk)
記上式爲ans,那麼答案應該爲10^ans,但是我們只要最高位的前三位,怎麼處理呢?
我們知道floor(log10(x))+1表示一個數在十進制下的位數,10^floor(log10(x))就是x最高位的十進制基(名詞是我口胡出來的...舉個例子,123,10^floor(log10(123))=100)
用10^ans除以10^floor(log10(ans)),整數部分就是最高位數,那麼用10^ans除以10^(floor(log10(ans))-2),整數部分就是最高位的三位數。
/* Forgive me Not */
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
typedef double DB;
typedef long double LD;
const int maxn = 1000005;
const LL p = 1000000000000LL;
int n, m, prime[maxn], cnt, mn[maxn], num[maxn];
bool isnotprime[maxn];
inline void getprime(int n) {
isnotprime[1] = 1;
for(int i = 2; i <= n; i++) {
if(!isnotprime[i]) prime[++cnt] = i, mn[i] = cnt;
for(int j = 1; j <= cnt && i * prime[j] <= n; j++) {
isnotprime[i * prime[j]] = 1;
mn[i * prime[j]] = j;
if(i % prime[j] == 0) break;
}
}
}
inline LL qpow(int a, int n) {
LL res = 1;
for(; n; n >>= 1, a = a * a % p) if(n & 1) res = res * a % p;
return res;
}
inline void add(int n, int f) {
for(; n > 1; n /= prime[mn[n]]) num[mn[n]] += f;
}
int main() {
scanf("%d%d", &n, &m);
getprime(n);
for(int i = 1; i <= n; i++) add(i, 1);
for(int i = 1; i <= m; i++) add(i, -1);
for(int i = 1; i <= n - m; i++) add(i, -1);
LL ans = 1; DB dig = 0.0;
for(int i = 1; i <= cnt; i++) if(num[i]) {
ans = ans * qpow(prime[i], num[i]) % p;
dig += log10(prime[i]) * num[i];
}
if(dig < 12) printf("%lld\n", ans);
else {
LD ans2 = pow(10, dig - (int)dig + 2);
printf("%lld...%lld\n", (LL)ans2, ans % 1000000000);
}
return 0;
}