部落人乘法是一种古老而巧妙的计算方式,通过减半和加倍运算实现乘法计算。这种方法虽然原始,但蕴含着深刻的数学原理,特别适合用来培养孩子的数学思维。
这个算法的核心思想是将乘法运算转化为加法和位移运算。具体步骤如下:
这种方法的数学原理基于二进制分解。例如13×15:
cpp复制#include <iostream>
#include <vector>
using namespace std;
void tribalMultiply(int a, int b) {
vector<pair<int, int>> steps;
int sum = 0;
string expression = "";
// 计算过程
while (a >= 1) {
steps.emplace_back(a, b);
if (a % 2 == 1) {
sum += b;
if (!expression.empty()) expression += "+";
expression += to_string(b);
}
a /= 2;
b *= 2;
}
// 输出计算过程
for (auto &step : steps) {
cout << step.first << "--------" << step.second;
if (step.first % 2 == 1) cout << " : 取" << step.second;
else cout << " : 划去";
cout << endl;
}
// 输出结果
cout << "结果为: " << expression << "=" << sum << endl;
}
int main() {
int a, b;
while (cin >> a >> b) {
tribalMultiply(a, b);
}
return 0;
}
注意:在实际编程中,a%2==1判断奇数比a%2!=0更准确,因为负数的取模结果可能为负。
这个问题要求将k个小球装入尽可能多的盒子,且满足:
数学上,这相当于将k分解为最长的连续正整数序列。例如k=8:
cpp复制#include <iostream>
#include <vector>
using namespace std;
vector<int> optimalBalls(int k) {
vector<int> result;
// 计算最大可能盒子数n:1+2+...+n ≤ k
int n = 1;
while (n*(n+1)/2 <= k) n++;
n--;
// 计算基础序列和剩余球数
int sum = n*(n+1)/2;
int remaining = k - sum;
// 分配剩余球数
for (int i=1; i<=n; i++) {
result.push_back(i + (i > n - remaining ? 1 : 0));
}
return result;
}
int main() {
int k;
while (cin >> k) {
auto res = optimalBalls(k);
for (int i=0; i<res.size(); i++) {
if (i != 0) cout << ",";
cout << res[i];
}
cout << endl;
}
return 0;
}
关键点:最大盒子数n满足1+2+...+n ≤ k,可通过解不等式n(n+1)/2 ≤ k得到。
回文数在任意进制下都应满足:
检测方法:
cpp复制#include <iostream>
#include <vector>
using namespace std;
// 检查数字a在进制base下是否为回文
bool isPalindromeInBase(int a, int base) {
if (a == 0) return true;
vector<int> digits;
while (a > 0) {
digits.push_back(a % base);
a /= base;
}
int left = 0, right = digits.size()-1;
while (left < right) {
if (digits[left] != digits[right]) return false;
left++;
right--;
}
return digits.back() != 0; // 首位不能为0
}
// 计算数字a在多少种进制(2-10)下是回文
int countPalindromeBases(int a) {
int count = 0;
for (int base = 2; base <= 10; base++) {
if (isPalindromeInBase(a, base)) count++;
}
return count;
}
int main() {
int N, S;
cin >> N >> S;
int found = 0;
for (int num = S+1; found < N; num++) {
if (countPalindromeBases(num) >= 2) {
cout << num << endl;
found++;
}
}
return 0;
}
优化技巧:对于大数检测,可以提前终止循环,当count≥2时立即返回。
双平方数集合S =
生成方法:
cpp复制vector<bool> isDoubleSquare(int M) {
int maxNum = 2*M*M;
vector<bool> isDS(maxNum+1, false);
for (int p=0; p<=M; p++) {
for (int q=0; q<=M; q++) {
isDS[p*p + q*q] = true;
}
}
return isDS;
}
cpp复制#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void findArithmeticSequences(int N, int M) {
vector<bool> isDS = isDoubleSquare(M);
vector<pair<int, int>> results;
int maxNum = 2*M*M;
// 枚举所有可能的b和a
for (int b=1; b*(N-1) <= maxNum; b++) {
for (int a=0; a + b*(N-1) <= maxNum; a++) {
bool valid = true;
for (int i=0; i<N; i++) {
if (!isDS[a + i*b]) {
valid = false;
break;
}
}
if (valid) {
results.emplace_back(a, b);
}
}
}
// 排序输出
sort(results.begin(), results.end(),
[](const pair<int,int>& x, const pair<int,int>& y) {
return x.second != y.second ? x.second < y.second : x.first < y.first;
});
for (auto& res : results) {
cout << res.first << " " << res.second << endl;
}
if (results.empty()) {
cout << "NONE" << endl;
}
}
性能优化:可以预先存储所有双平方数,减少重复计算。
A-B表示在A中但不在B中的元素。实现要点:
cpp复制#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> setDifference(vector<int>& A, vector<int>& B) {
sort(A.begin(), A.end());
sort(B.begin(), B.end());
vector<int> result;
int i = 0, j = 0;
while (i < A.size() && j < B.size()) {
if (A[i] < B[j]) {
if (result.empty() || A[i] != result.back()) {
result.push_back(A[i]);
}
i++;
} else if (A[i] > B[j]) {
j++;
} else {
i++;
j++;
}
}
while (i < A.size()) {
if (result.empty() || A[i] != result.back()) {
result.push_back(A[i]);
}
i++;
}
return result;
}
int main() {
int T;
cin >> T;
while (T--) {
int n, m;
cin >> n >> m;
vector<int> A(n), B(m);
for (int i=0; i<n; i++) cin >> A[i];
for (int i=0; i<m; i++) cin >> B[i];
auto res = setDifference(A, B);
if (res.empty()) {
cout << "NULL\n";
} else {
for (int num : res) cout << num << " ";
cout << endl;
}
}
return 0;
}
输出格式注意:题目要求每个元素后跟空格,包括最后一个元素后也要有空格和换行。