P3799 妖梦拼木棒
妖梦拼木棒
题目背景
上道题中,妖梦斩了一地的木棒,现在她想要将木棒拼起来。
题目描述
有
答案对
输入格式
第一行一个整数
第二行往下
输出格式
一行一个整数代表答案。
样例 #1
样例输入 #1
4
1
1
2
2
样例输出 #1
1
提示
数据规模与约定
- 对于
的数据,保证 。 - 对于
的数据,保证 , 。
2.题解
2.1 子集枚举
错误思路
看到从n个里面选4个,自然而然想到了子集枚举,但是自己错误估计了范围
由于子集枚举中会用到 1 << n, 而
错误代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
long long ans = 0;
cin >> n;
if(n < 4) cout << 0;
vector<int> arr(n);
for(int i = 0; i < n; i++)
cin >> arr[i];
long long U = 1 << n;
for(long long S = 0; S < U; S++){
if(__builtin_popcount(S) == 4){
vector<int> tmp;
for(int i = 0; i < n; i++){
if(S & (1 << i)) tmp.push_back(arr[i]);
}
sort(tmp.begin(), tmp.end());
if(tmp[0] + tmp[1] == tmp[2] && tmp[2] == tmp[3])
ans++;
// if((tmp[0] == tmp[1] && tmp[1] == tmp[2]) || (tmp[0] == tmp[1] && tmp[1] == tmp[3])
// || (tmp[0] == tmp[2] && tmp[2] == tmp[3]) || (tmp[1] == tmp[2] && tmp[2] == tmp[3]) )
// ans++;
}
}
// cout << ans % static_cast<int>(1e9 + 7); // 使用 1e9 表示科学计数法中的 $10^9$,但它是一个 double 类型的浮点数,而不是整数,% 操作符使用时,左右操作数都必须是整数
cout << ans % 1000000007;
}
2.2 循环枚举
思路
由于 0 <= n <= 5000, 且
同时记录最小数和最大数,方便后面循环使用。
这里我们最开始的思路是四重循环,分别表示四根火柴棒的长度,但是
我们寻找它们之间的关系,要构成一个等边三角形,首先有两个数一定是相等的,另外两个数的和也和前者相等。
所以我们其实只需要两重循环,分别表示两个作为和的数,并用他们的和去我们的数组中寻找有没有两个以上该长度的火柴棒即可
这里注意一下:
1.对于两个作为和的数,相等和不相等的时候可以分出来讨论一下,也可以不用。
2.第二层循环必定是[i, maxNum],就比如像之前已经找过长度为1和长度为2的火柴棒了,再去找长度为2的火柴棒和长度为1的火柴棒就重复了!!!
代码
#include<bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
int C(int n, int k){
if(k == 1) return n;
else if(k == 2) return n * (n - 1) / 2;
}
int main(){
int n;
long long ans = 0;
cin >> n;
if(n < 4) cout << 0;
vector<int> arr(10001);
int maxNum = 5000, minNum = 0;
for(int i = 0; i < n; i++){
int tmp;
cin >> tmp;
arr[tmp]++;
maxNum = max(maxNum, tmp);
minNum = min(minNum, tmp);
}
for(int i = minNum; i <= maxNum; i++){
for(int j = i; j <= maxNum; j++){
if(i + j > maxNum) break;
if(i == j){
if(arr[i << 1] >= 2 && arr[i] >= 2){
ans = (ans + C(arr[i], 2) * C(arr[i << 1], 2)) % MOD;
}
}
else{
if(arr[i + j] >= 2 && arr[i] >= 1 && arr[j] >= 1){
ans = (ans + C(arr[i], 1) * C(arr[j], 1) * C(arr[i + j], 2)) % MOD;
}
}
}
}
cout << ans % MOD;
}
分类:
洛谷
, 数据结构与算法 / 枚举 / 循环枚举
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了