传送门: https://zoj.pintia.cn/problem-sets/91827364500/problems/91827370217
题意
起
点
在
0
点
,
有
n
步
,
每
一
步
有
1
4
往
左
走
、
1
4
往
右
走
、
1
2
不
动
。
起点在0点,有n步,每一步有\frac{1}{4}往左走、\frac{1}{4}往右走、\frac{1}{2}不动。
起点在0点,有n步,每一步有41往左走、41往右走、21不动。
已
知
终
点
在
点
m
,
问
所
有
方
案
到
达
m
时
P
Q
是
多
少
,
请
对
1
e
9
+
7
取
模
。
已知终点在点m,问所有方案到达m时\frac{P}{Q}是多少,请对1e9+7取模。
已知终点在点m,问所有方案到达m时QP是多少,请对1e9+7取模。
思路
假
设
往
左
走
了
x
步
,
往
右
走
了
y
步
,
z
步
不
动
,
即
可
得
:
假设往左走了x步,往右走了y步,z步不动,即可得:
假设往左走了x步,往右走了y步,z步不动,即可得:
x
、
−
x
+
y
=
m
、
x
+
y
+
z
=
n
,
得
:
x、-x+y=m、x+y+z=n,得:
x、−x+y=m、x+y+z=n,得:
x
>
=
0
x>=0
x>=0
y
=
x
+
m
≥
0
→
x
≥
−
m
y=x+m\ge 0 \rightarrow x\ge -m
y=x+m≥0→x≥−m
z
=
n
−
x
−
y
≥
0
→
x
≤
n
−
m
2
z=n-x-y\ge 0 \rightarrow x\leq \frac{n-m}{2}
z=n−x−y≥0→x≤2n−m
所 以 x 的 范 围 为 [ m a x ( − m , 0 ) , n − m 2 ] 所以x的范围为[max(-m, 0),\frac{n-m}{2}] 所以x的范围为[max(−m,0),2n−m]
对
于
每
一
个
x
的
贡
献
为
C
n
x
(
1
4
)
x
∗
C
n
−
x
y
(
1
4
)
y
∗
1
2
z
,
变
量
替
换
一
下
得
:
对于每一个x的贡献为C_n^x(\frac{1}{4})^x*C_{n-x}^y(\frac{1}{4})^y*\frac{1}{2}^z,变量替换一下得:
对于每一个x的贡献为Cnx(41)x∗Cn−xy(41)y∗21z,变量替换一下得:
a
n
s
=
(
1
2
)
n
+
m
∗
∑
x
=
m
a
x
(
−
m
,
0
)
n
−
m
2
C
n
x
C
n
−
x
x
+
m
(
1
4
)
x
ans=(\frac{1}{2})^{n+m}*\sum_{x=max(-m,0)}^{\frac{n-m}{2}}C_n^xC_{n-x}^{x+m}(\frac{1}{4})^x
ans=(21)n+m∗x=max(−m,0)∑2n−mCnxCn−xx+m(41)x
算 之 前 要 判 断 x 的 范 围 是 否 错 误 即 可 。 算之前要判断x的范围是否错误即可。 算之前要判断x的范围是否错误即可。
Code
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
ll mod = 1e9 + 7;
ll quick_pow(ll a, ll b) {
ll ans = 1;
while(b > 0) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans % mod;
}
const int N = 1e5 + 10;
ll f[N], inv[N], invF[N];
void Init() {
f[0] = f[1] = inv[0] = inv[1] = invF[0] = invF[1] = 1;
for(int i = 2;i < N; i++) {
f[i] = f[i - 1] * i % mod;
inv[i] = mod - (mod / i) * inv[mod % i] % mod;
invF[i] = invF[i - 1] * inv[i] % mod;
}
}
ll C(ll m, ll n) {
if(m < 0 || n < 0 || n > m)
return 0;
ll ans = f[m];
ans = ans * invF[n] % mod;
ans = ans * invF[m - n] % mod;
return ans;
}
void solve() {
Init();
int _; scanf("%d",&_);
ll inv2 = quick_pow(2, mod - 2);
ll inv4 = quick_pow(4, mod - 2);
while(_--) {
ll n, m;
scanf("%lld%lld",&n,&m);
if(abs(m) > n) {
printf("0\n");
continue;
}
ll xo = max(-m, 0ll), xn = (n - m) / 2;
ll ans = quick_pow(inv2, n + m);
ll res = 0;
for(ll i = xo;i <= xn; i++) {
res += quick_pow(inv4, i) * C(n, i) % mod * C(n - i, m + i) % mod;
res %= mod;
}
ans = ans * res % mod;
printf("%lld\n",(ans + mod) % mod);
}
}
signed main() {
solve();
}