洛谷 SP19148 / SPOJ INS14G Kill them All
比较经典的一道题。
思路
第一个怪物一定是 Digo 杀的,考虑第二个到最后一个怪物,如果忽略掉 Digo 杀的第一只怪物,那么每杀掉一只怪物后,Digo 的击杀数都不少于 Sharry 的击杀数。
假设现在在一个平面直角坐标系,位于点 ,Digo 杀一个怪物则向右上走一步,即 ;Sharry 杀一个怪物则向右下走一步,即 。则题要求的就是从 走 步且任意时刻纵坐标 ,即不越过或在直线 上的方案数。
考虑枚举终点坐标 ,其中 且 。如果不考虑纵坐标 的限制,则从 走到 的方案数为 。现在要减去不合法情况的方案数,设路径第一次与 交于点 ,将路径横坐标 的部分沿 翻折,则终点变为 。因为从 到 一定要经过 ,所以不合法情况的方案数其实就是 到 的方案数,即 。
那么答案为
容易发现式子的项可以相互抵消,因此当 时答案为 , 时答案为 。
代码
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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】