目录
亿点小想法:
- 拼木棒,这个题很基础,但是我完全想不到枚举长度这种方式,也没想到可以搞个桶,把木棒长度
i出现的次数放在cnt[i]中。- 学到了一个新知识,以
(i, j)为右下角元素的正方形个数为min(i, j),所有矩形(包括正方形)个数为i * j。
1. P3799 小 Y 拼木棒
题目背景
上道题中,小 Y 斩了一地的木棒,现在她想要将木棒拼起来。
题目描述
有
n
n
n 根木棒,现在从中选
4
4
4 根,想要组成一个正三角形,问有几种选法?
答案对
1
0
9
+
7
10^9+7
109+7 取模。
输入格式
第一行一个整数
n
n
n。
第二行往下
n
n
n 行,每行
1
1
1 个整数,第
i
i
i 个整数
a
i
a_i
ai 代表第
i
i
i 根木棒的长度。
输出格式
一行一个整数代表答案。
输入输出样例 #1
输入 #1
4
1
1
2
2
输出 #1
1
说明/提示
数据规模与约定
- 对于 30 % 30\% 30% 的数据,保证 n ≤ 5 × 1 0 3 n \le 5 \times 10^3 n≤5×103。
- 对于
100
%
100\%
100% 的数据,保证
1
≤
n
≤
1
0
5
1 \leq n \le 10^5
1≤n≤105,
1
≤
a
i
≤
5
×
1
0
3
1 \le a_i \le 5 \times 10^3
1≤ai≤5×103。
关于标题:因为一些不可抗力的原因,名称进行了更改。深表歉意。
代码
#include <iostream>
using namespace std;
const int N = 1e5 + 10, M = 5e3 + 10, INF = 1e9 + 7;
typedef long long LL;
LL res;
int cnt[M];// 统计一下木棒各长度出现次数,由题意知最大长度为5e3
int n;
int C1(int x)
{
return x;
}
int C2(int x)
{
return x * (x - 1) / 2;
}
int main()
{
cin >> n;
while (n --)
{
int x;
cin >> x;
cnt[x] ++;
}
// 对于木棒长度abcd存在如下关系:a = b = c + d
// 可以只枚举木棒长度a和c,c为1 ~ a/2,d为(a/2 + 1) ~ a
for (int a = 1; a <= 5000; a ++)
{
for (int c = 1; c <= a / 2; c ++)
{
int d = a - c;
if (c != d)
{
if (cnt[a] >= 2 && cnt[c] >= 1 && cnt[d] >= 1)
res += (LL) C2(cnt[a]) * C1(cnt[c]) * C1(cnt[d]) % INF;
}
else
{
if (cnt[a] >= 2 && cnt[c] >= 2)
res += (LL) C2(cnt[a]) * C2(cnt[c]) % INF;
}
// 要再取下模,不然会寄
res = res % INF;
}
}
cout << res << endl;
return 0;
}
2. P2241 统计方形(数据加强版)
题目背景
1997年普及组第一题
题目描述
有一个 n × m n \times m n×m 方格的棋盘,求其方格包含多少正方形、长方形(不包含正方形)。
输入格式
一行,两个正整数 n , m n,m n,m( n ≤ 5000 , m ≤ 5000 n \leq 5000,m \leq 5000 n≤5000,m≤5000)。
输出格式
一行,两个正整数,分别表示方格包含多少正方形、长方形(不包含正方形)。
输入输出样例 #1
输入 #1
2 3
输出 #1
8 10
代码
#include <iostream>
using namespace std;
typedef long long LL;
LL sq_cnt, all_cnt;
int n, m;
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
{
// 以(i, j)为右下角元素
// 正方形个数为min(i, j)
// 总的矩形(包括正方形)个数为i * j
sq_cnt += LL(min(i, j));
all_cnt += LL(i * j);
}
cout << sq_cnt << ' ' << all_cnt - sq_cnt << endl;
return 0;
}
1340

被折叠的 条评论
为什么被折叠?



