1 条题解
-
0
要解决这个齿轮比实现的问题,关键在于将机械传动的问题转化为数学上的质因数分解与覆盖问题。以下是详细的解题思路:
问题分析
齿轮传动比的计算规则是:总传动比等于各齿轮对传动比的乘积。若主动轮齿数为 ,从动轮齿数为 ,则该齿轮对的传动比为 。整个系统的总传动比是各齿轮对传动比的乘积。
核心思路
-
数学建模:
设目标传动比为 ,约分后为 (其中 ,)。
齿轮组中每个齿轮的齿数可表示为 ,其中 是齿轮组的最小齿数, 为整数(题目保证所有齿数是 的倍数)。 -
质因数分解:
- 对 和 进行质因数分解,得到它们的质因数集合。
- 若 和 的所有质因数都能由齿轮组的 的质因数组合而成,则传动比可实现。
具体步骤
-
预处理齿轮组:
- 找到最小齿数 ,计算每个齿轮的 。
- 收集所有 的质因数,形成可覆盖的质因数集合。
-
处理目标传动比:
- 计算 ,将 约分为 。
- 若 ,直接不可实现(但题目中,故无需处理)。
-
质因数覆盖检查:
- 分解 的质因数,检查每个质因数是否能被 的质因数覆盖。
- 分解 的质因数,同样检查覆盖性。
- 若 和 均满足覆盖条件,则传动比可实现。
C++实现:
#include <iostream> #include <algorithm> using namespace std; const int N = 64; const int M = 10010; const int INF = 1 << 30; int num[N], n, m, qa, qb; bool stat[M]; // 全局状态数组,标记可实现的齿轮比 // 计算最大公约数(GCD) int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } // 判断 qa:qb 是否可以由已有的齿轮比组合得到 bool judge(int a, int b) { for (int i = 1; i * a < M && i * b < M; ++i) { if (stat[i * a] && stat[i * b]) { return true; } } return false; } // 预处理所有可能的齿轮比 void pre() { int i, j, tmp; cin >> n; int num_input[N]; // 使用固定大小的数组 for (i = 0; i < n; ++i) { cin >> num_input[i]; } // 收集所有可能的齿轮比(num[i]/num[j] 的约简形式) int temp_fac[N * N]; // 临时存储因子 int top = 0; for (i = 0; i < n; ++i) { for (j = 0; j < n; ++j) { if (i == j) continue; if (num_input[i] % num_input[j] == 0) { temp_fac[top++] = num_input[i] / num_input[j]; } } } // 初始化 stat 数组 for (i = 0; i < M; ++i) { stat[i] = false; } stat[1] = true; // 1:1 是基础比例 // 动态规划计算所有可能的齿轮比 for (i = 0; i < top; ++i) { int current_fac = temp_fac[i]; for (j = 1; j * current_fac < M; ++j) { if (stat[j]) { tmp = j * current_fac; if (tmp < M) { stat[tmp] = true; } } } } } int main() { int testcase, testid, a, b; cin >> testcase; for (testid = 1; testid <= testcase; ++testid) { pre(); // 预处理当前测试用例的齿轮比 cin >> m; cout << "Scenario #" << testid << ":" << endl; while (m--) { cin >> a >> b; int d = gcd(a, b); qa = a / d; qb = b / d; if (judge(qa, qb)) { cout << "Gear ratio " << a << ":" << b << " can be realized." << endl; } else { cout << "Gear ratio " << a << ":" << b << " cannot be realized." << endl; } } cout << endl; // 输出空行分隔测试用例 if (testid < testcase) { // 重置 stat 数组 for (int i = 0; i < M; ++i) { stat[i] = false; } } } return 0; }
-
- 1
信息
- ID
- 396
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者