洛谷 P3214 [HNOI2011] 卡农 题解
题目链接
题解
不难发现其实题目意思就是让我们从
- 每个方案必须本质不同
- 不能选择相同的集合
的每个数出现次数必须是偶数
第一个限制是好解决的, 我们只需要在求出所有的有序方案数之后除以
现在我们考虑一个一个集合的加入, 对于第
但是这样并不是正确的, 因为假如我们选完前
这样我们就把这道题解决了.
代码
#include <bits/stdc++.h>
using i64 = long long;
constexpr int P = 1e8 + 7;
i64 power(i64 a, i64 b)
{
i64 res = 1;
for( ; b; b >>= 1, a = a * a % P)
if(b & 1) res = res * a % P;
return res;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m; std::cin >> n >> m;
std::vector<i64> fac(m + 1, 1);
i64 pw = power(2, n) - 1;
if(pw < 0) pw += P;
for(int i = 1; i <= m; i++) fac[i] = fac[i - 1] * (pw - i + 1) % P;
std::vector<i64> f(m + 1);
f[0] = 1, f[1] = 0;
for(int i = 2; i <= m; i++)
{
f[i] = fac[i - 1];
f[i] -= f[i - 1];
f[i] -= (pw - i + 2) * f[i - 2] % P * (i - 1) % P;
f[i] %= P;
if(f[i] < 0) f[i] += P;
}
std::vector<i64> inv(m + 1);
inv[1] = 1;
for(int i = 2; i <= m; i++) inv[i] = (P - P / i) * inv[P % i] % P;
for(int i = 2; i <= m; i++) inv[i] = inv[i] * inv[i - 1] % P;
std::cout << f[m] * inv[m] % P << "\n";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!