HDOJ:6333-Problem B. Harvest of Apples(组合数学+莫队算法+逆元)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6333
解题心得:
- 这个题可以说是十分精彩了,首先推组合数学的公式,其中一个很重要的公式是Cnm = Cmn-1 + Cm-1n-1 这个公式知道杨辉三角的都明白,但是一看发现似乎没啥用。但是可以以这个公式为基础继续推演下去。
- 设Snm = Cn1 + Cn2 + Cn3 + ...... Cnm 然后继续使用上面的基本公式可以化成
- Sn m-1 = Sn m - Cn m
Sn m+1 = Sn m + Cn m+1
Sn+1 m = 2Sn m - Cn m
Sn m = (Sn+1 m + Cn m)/2 - 这些个公式看起来没啥用,但是知道S的关系之间可以通过O(1)的复杂度来进行转化,这样就可以将105次询问离线化处理,也就是用莫队来维护。神奇阿,想破脑袋就是想不到阿。里面的除法取余的操作用逆元来处理,逆元可以先全与预处理出来。
// // ┏┛ ┻━━━━━┛ ┻┓ // ┃ ┃ // ┃ ━ ┃ // ┃ ┳┛ ┗┳ ┃ // ┃ ┃ // ┃ ┻ ┃ // ┃ ┃ // ┗━┓ ┏━━━┛ // ┃ ┃ 神兽保佑 // ┃ ┃ 代码无BUG! // ┃ ┗━━━━━━━━━┓ // ┃ ┣┓ // ┃ ┏┛ // ┗━┓ ┓ ┏━━━┳ ┓ ┏━┛ // ┃ ┫ ┫ ┃ ┫ ┫ // ┗━┻━┛ ┗━┻━┛ #include <bits/stdc++.h> using namespace std; const int maxn = 1e5+100; const int MOD = 1e9+7; typedef long long ll; struct Query { ll n, m, B, pos, ans; }q[maxn]; ll unit, ans, fac[maxn], inv[maxn], t, rev2; ll quick_pow(ll a, ll b) { ll res = 1; while(b) { if(b&1) res = res * a % MOD; a = a * a % MOD; b >>= 1; } return res; } void get_fac() { //预处理出阶乘和逆元 fac[0] = 1; fac[1] =1; for(int i=2;i<maxn;i++) { fac[i] = i * fac[i-1] % MOD; } //神奇的操作 inv[maxn-1] = quick_pow(fac[maxn-1], MOD-2); for(int i=maxn-2;i>=0;i--) { inv[i] = inv[i+1] * (i + 1) % MOD; } } bool cmp1(Query a, Query b) { if(a.B == b.B) return a.m < b.m; return a.B < b.B; } bool cmp2(Query a, Query b) { return a.pos < b.pos; } void init() { unit = sqrt(maxn); get_fac(); scanf("%lld", &t); for(int i=0;i<t;i++) { scanf("%lld%lld", &q[i].n, &q[i].m); q[i].B = q[i].n/unit; q[i].pos = i; } rev2 = quick_pow(2, MOD-2); sort(q, q+t, cmp1); } ll C(ll n, ll m) {//得到c(n, m)的组合 ll ans = fac[n] * inv[n-m] % MOD * inv[m] % MOD; return ans; } void addL(ll l, ll r) { ans = ((2 * ans % MOD) + MOD - C(l, r)) % MOD; } void cutL(ll l, ll r) { ans = (ans + C(l-1, r) % MOD) * rev2 % MOD; } void addR(ll l, ll r) { ans = (ans + C(l, r+1)) % MOD; } void cutR(ll l, ll r) { ans = (ans + MOD - C(l, r)) % MOD; } int main() { init(); ll l=1, r = 1; ans = 2; for(int i=0;i<t;i++) {//离线莫队处理 int L = q[i].n; int R = q[i].m; while(l < L) addL(l++, r); while(l > L) cutL(l--, r); while(r > R) cutR(l, r--); while(r < R) addR(l, r++); q[i].ans = ans; } sort(q, q+t, cmp2); for(int i=0;i<t;i++) { printf("%lld\n",q[i].ans); } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库