P3799 妖梦拼木棒
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MOD = 1e9 + 7;//要模的质数
const int N = 1e5 + 10;
int a[N]; //木棍长度数组,木棍数量最大值是10^5,所以N需要开到1e5+10
int b[N]; //每个长度的木棍出现的次数
int n; //n根木棍
int MAX; //木棍的最大长度
LL res; //结果,为防止在运算过程中暴INT,声明成LL
//组合数迭代模板
int c[N][4]; //为什么要声明N*5维的数组呢?第一维是说,最多可能需要从N个元素中取,第二维是说,最多取4个.为啥是4个呢?因为题目说取四根最多了
void init() {
for (int i = 0; i < N; i++)
for (int j = 0; j <= min(i, 4); j++)
if (!j)c[i][j] = 1;
else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD;
}
int main() {
//生成数据范围内的所有组合数
init();
//n根木棒
cin >> n;
//输入数据
for (int i = 1; i <= n; ++i) {
cin >> a[i];
//1、记录输入的最大值
MAX = max(a[i], MAX);
//2、使用桶记录每个长度出现的次数
b[a[i]]++;
}
//遍历每一个可能存在的长度
for (int i = 2; i <= MAX; i++) {
//只有出现两次及以上的边才有机会成为长边
if (b[i] >= 2) {
//在b[i]中取2个有多少种方法,记得每步取模
LL cnt = c[b[i]][2];
//要从剩余的木棒中取出2根长度之和为i的木棒。令其中一根长度为j,则另一根长度为i-j。
for (int j = 1; j <= i / 2; j++) {
//如果两根一样长,那么就需要这个小的最小有2根
//另一根就是i-j的长度
if (i == 2 * j && b[j] >= 2)
res += cnt * c[b[j]][2] % MOD;
//两种情况之间是加法原理
//用来合成的木棒长度不等
if (i != 2 * j && b[j] >= 1 && b[i - j] >= 1)
res += cnt * c[b[j]][1] * c[b[i - j]][1] % MOD;
//一定注意随时取模
res %= MOD;
}
}
}
printf("%lld", res);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2017-11-23 利用WINDOWS活动目录提供LDAP的方案
2017-11-23 Centos6.9下安装OpenOffice 4.1.4
2017-11-23 CentOS 7下OpenLDAP编译安装及配置
2014-11-23 现行技术体系的问题总结