// 不想思考暴力法
#include <bits/stdc++.h>
using namespace std;
int main() {
// N 非零个位 任意两个组合成二位数字
// 求所有可能组合数之和
int n, sum = 0, a[10];
cin >> n;
for(int i = 0; i < n; i++)
cin >> a[i];
// 一重循环 固定第一个元素十位
for(int i = 0; i < n; i++){
// 二重循环获取个位
for(int j = i + 1; j < n; j++)
sum += a[i] * 10 + a[j];
}
// 翻转再来一次
reverse(a, a + n);
for(int i = 0; i < n; i++){
// 二重循环获取个位
for(int j = i + 1; j < n; j++)
sum += a[i] * 10 + a[j];
}
cout << sum;
}
// 文艺简化版
#include <bits/stdc++.h>
using namespace std;
int main() {
// N 非零个位 任意两个组合成二位数字
// 求所有可能组合数之和
int n, tmp, sum = 0;
cin >> n;
for(int i = 0; i < n; i++){
cin >> tmp;
sum += tmp;
}
cout << sum * (n - 1) * 11;
}
看了看时间似乎没什么需求,况且是15分的题目,暴力一边过了。
本来还想这种组合会不会溢出,一看只有10个数并且还是两位,就没有考虑了。
学一下别人找规律。当时直接就想到的是排列组合,没想到还有人会往这个方向去想。
方法是先分类然后归纳关系,可以看到每个数字都会分别出现在个位和十位,比如 2 5 就有 25 和 52, 两个数分别做了一次个位和十位。当 2 8 , 5 8 时同理。
然后将这几个数字的全部组合列出来。
25 + 28 + 58 + 85 + 82 + 52
按照刚才的想法将个位和十位拆开分类。
20 + 5 + 20 + 8 + 50 + 8 + 80 + 5 + 80 + 2 + 50 + 2 =
20 + 20 + 50 + 50 + 80 + 80 + 2 + 2 + 5 + 5 + 8 + 8
可以看到在三个数的情况下,每个数在不同的位置上都出现了两次。用进制将他们化在一起就有。
2 * (20 + 50 + 80) + 2 * (2 + 5 + 8) =
2 * 10 * (2 + 5 + 8) + 2 * (2 + 5 + 8) =
2 * 11 * (2 + 5 + 8)
括号内是出现的数字相加,外面 11 是固定的, 2 是数字的个数减一 n - 1,这样就可以得到这题的比较简单的公式。
不过看不同位置出现次数,似乎之前哪个题目也有这样的思路。找了找是 1049 数列的片段和 这个题目。不过那个纯粹是因为暴力解不了,所以得找规律来化简一下。
至于是不是都是11这个常数可以自个多一两个数字验证一下,反正我也是剽窃来的只是随便解释一下。