洛谷 SP19148 / SPOJ INS14G Kill them All

洛谷传送门

SPOJ 传送门

比较经典的一道题。

思路

第一个怪物一定是 Digo 杀的,考虑第二个到最后一个怪物,如果忽略掉 Digo 杀的第一只怪物,那么每杀掉一只怪物后,Digo 的击杀数都不少于 Sharry 的击杀数。

假设现在在一个平面直角坐标系,位于点 (0,0),Digo 杀一个怪物则向右上走一步,即 (x,y)(x+1,y+1);Sharry 杀一个怪物则向右下走一步,即 (x,y)(x+1,y1)。则题要求的就是从 (0,0)n1 步且任意时刻纵坐标 0,即不越过或在直线 y=1 上的方案数。

考虑枚举终点坐标 (n1,k),其中 0kn12(n+k1)。如果不考虑纵坐标 0 的限制,则从 (0,0) 走到 (n1,k) 的方案数为 Cn1n+k12。现在要减去不合法情况的方案数,设路径第一次与 y=1 交于点 (m,1),将路径横坐标 m 的部分沿 y=1 翻折,则终点变为 (n1,k2)。因为从 (0,0)(n1,k2) 一定要经过 y=1,所以不合法情况的方案数其实就是 (0,0)(n1,k2) 的方案数,即 Cn1n+k+12

那么答案为

k=0n1[2(n+k1)]Cn1n+k12Cn1n+k+12

容易发现式子的项可以相互抵消,因此当 2n 时答案为 Cn1n22n 时答案为 Cn1n12

代码

code
/*
p_b_p_b txdy
AThousandSuns txdy
Wu_Ren txdy
Appleblue17 txdy
*/
#include <bits/stdc++.h>
#define pb push_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;
const int maxn = 1000100;
const int N = 1000000;
const ll mod = 1000000007;
ll fac[maxn], ifac[maxn], n;
ll qpow(ll b, ll p) {
ll res = 1;
while (p) {
if (p & 1) {
res = res * b % mod;
}
b = b * b % mod;
p >>= 1;
}
return res;
}
void init() {
fac[0] = 1;
for (int i = 1; i <= N; ++i) {
fac[i] = fac[i - 1] * i % mod;
}
ifac[N] = qpow(fac[N], mod - 2);
for (int i = N - 1; ~i; --i) {
ifac[i] = ifac[i + 1] * (i + 1) % mod;
}
}
ll C(ll n, ll m) {
if (n < m || n < 0 || m < 0) {
return 0;
} else {
return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
}
}
void solve() {
scanf("%lld", &n);
if (n & 1) {
printf("%lld\n", C(n - 1, (n - 1) / 2));
} else {
printf("%lld\n", C(n - 1, n / 2));
}
}
int main() {
init();
int T = 1;
scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}
posted @   zltzlt  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示