[SPOJ UCV2013E Greedy Walking]数学、统计
分类:数学
逆元
水题
1. 题目链接
[SPOJ UCV2013E Greedy Walking]
2. 题意描述
有一个
N
维空间,规定起点
- 一次移动一个单位
- 一次只能在某一个维度移动一步
- 每步都只能朝正方向移动。
3. 解题思路
水题。直接可以求出方案数公式。然后就可以O(N)直接预处理出阶乘,以及阶乘的逆元。
方案数公式为:
令:zi=abs(xi−yi);sum=∑i=1nzi;则ans=sum!∏ni=1(zi!)
4. 实现代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double LB;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int INF = 0x3f3f3f3f;
const LL INFL = 0x3f3f3f3f3f3f3f3fLL;
const LB eps = 1e-8;
const int MAXN = 50 + 5;
const int MX = 500 * 50 + 5;
const int MOD = 1000000007;
int n, x[MAXN], y[MAXN], z[MAXN];
LL fac[MX], inv[MX];
LL qpow(LL a, LL b) {
LL ret = 1;
while(b > 0) {
if(b & 1) ret = ret * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ret;
}
void init() {
fac[0] = 1;
for(int i = 1; i < MX; ++i) fac[i] = fac[i - 1] * i % MOD;
inv[MX - 1] = qpow(fac[MX - 1], MOD - 2);
for(int i = MX - 2; i >= 0; --i) inv[i] = inv[i + 1] * (i + 1) % MOD;
}
int main() {
#ifdef ___LOCAL_WONZY___
freopen("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
init();
while(~scanf("%d", &n) && n) {
for(int i = 1; i <= n; ++i) scanf("%d", &x[i]);
for(int i = 1; i <= n; ++i) scanf("%d", &y[i]);
LL ans = 1, sum = 0;
for(int i = 1; i <= n; ++i) {
z[i] = abs(x[i] - y[i]);
sum += z[i];
}
ans = fac[sum];
for(int i = 1; i <= n; ++i) {
ans = ans * inv[z[i]] % MOD;
}
printf("%lld\n", ans);
}
return 0;
}