HDU - 5912 - Fraction (模拟)

本文介绍了一个关于分数加法的编程挑战,需要计算特殊形式的分数并确保结果为最简形式。文章提供了完整的AC代码实现,包括输入输出示例、算法思路和最大公约数的计算方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接
Mr. Frog recently studied how to add two fractions up, and he came up with an evil idea to trouble you by asking you to calculate the result of the formula below:
这里写图片描述

As a talent, can you figure out the answer correctly?
Input
The first line contains only one integer T, which indicates the number of test cases.

For each test case, the first line contains only one integer n (n≤8).

The second line contains n integers: a1,a2,⋯an(1≤ai≤10a1,a2,⋯an(1≤ai≤10).
The third line contains n integers: b1,b2,⋯,bn(1≤bi≤10)b1,b2,⋯,bn(1≤bi≤10).
Output
For each case, print a line “Case #x: p q”, where x is the case number (starting from 1) and p/q indicates the answer.

You should promise that p/q is irreducible.
Sample Input
1
2
1 1
2 3
Sample Output
Case #1: 1 2

Hint
Here are the details for the first sample:
2/(1+3/1) = 1/2

题目就是让你求一个如图所示的分数的分子和分母。其实也没啥好办法啊,就是模拟呗,我们平时怎么算的分数还是怎么算啊。刚开始我想的是直接用递归来算出分母的值,发现一只wa,emmm,后来想了想,确实,这样做的话总会有精度损失的,所以还是模拟吧。还有就是,他要求不能再约分,所以还要有一个求最大公约数的函数。具体的话,还是看代码吧,其实主要的就是涉及了分子分母之间的转化。
AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[10], b[10];
int n;

int gcd(int x, int y)
{
    return y == 0 ? x : gcd(y, x % y);
}

int main()
{
    int t;
    scanf("%d", &t);
    for(int T = 1; T <= t; T++)
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for(int i = 1; i <= n; i++) scanf("%d", &b[i]);
        int x, y;
        x = b[n], y = a[n];
        for(int i = n - 1; i >= 1; i--)
        {
            int temp = a[i] * y + x;
            x = y;  y = temp;
            x *= b[i];
        }
        int _gcd = gcd(x, y);
        printf("Case #%d: %d %d\n", T, x / _gcd, y / _gcd);
    }
    return 0;
}
HDU-3480 是一个典型的动态规划问题,其题目标题通常为 *Division*,主要涉及二维费用背包问题或优化后的动态规划策略。题目大意是:给定一个整数数组,将其划分为若干个连续的子集,每个子集最多包含 $ m $ 个元素,并且每个子集的最大值与最小值之差不能超过给定的阈值 $ t $,目标是使所有子集的划分代价总和最小。每个子集的代价是该子集最大值与最小值的差值。 ### 动态规划思路 设 $ dp[i] $ 表示前 $ i $ 个元素的最小代价。状态转移方程如下: $$ dp[i] = \min_{j=0}^{i-1} \left( dp[j] + cost(j+1, i) \right) $$ 其中 $ cost(j+1, i) $ 表示从第 $ j+1 $ 到第 $ i $ 个元素构成一个子集的代价,即 $ \max(a[j+1..i]) - \min(a[j+1..i]) $。 为了高效计算 $ cost(j+1, i) $,可以使用滑动窗口或单调队列等数据结构来维护区间最大值与最小值,从而将时间复杂度优化到可接受的范围。 ### 示例代码 以下是一个简化版本的动态规划实现,使用暴力方式计算区间代价,适用于理解问题结构: ```cpp #include <bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 10010; int a[MAXN]; int dp[MAXN]; int main() { int T, n, m; cin >> T; for (int Case = 1; Case <= T; ++Case) { cin >> n >> m; for (int i = 1; i <= n; ++i) cin >> a[i]; dp[0] = 0; for (int i = 1; i <= n; ++i) { dp[i] = INF; int mn = a[i], mx = a[i]; for (int j = i; j >= max(1, i - m + 1); --j) { mn = min(mn, a[j]); mx = max(mx, a[j]); if (mx - mn <= T) { dp[i] = min(dp[i], dp[j - 1] + mx - mn); } } } cout << "Case " << Case << ": " << dp[n] << endl; } return 0; } ``` ### 优化策略 - **单调队列**:可以使用两个单调队列分别维护当前窗口的最大值与最小值,从而将区间代价计算的时间复杂度从 $ O(n^2) $ 降低到 $ O(n) $。 - **斜率优化**:若问题满足特定的决策单调性,可以考虑使用斜率优化技巧进一步加速状态转移过程。 ### 时间复杂度分析 原始暴力解法的时间复杂度为 $ O(n^2) $,在 $ n \leq 10^4 $ 的情况下可能勉强通过。通过单调队列优化后,可以稳定运行于 $ O(n) $ 或 $ O(n \log n) $。 ### 应用场景 HDU-3480 的问题模型可以应用于资源调度、任务划分等场景,尤其适用于需要控制子集内部差异的问题,如图像分块压缩、数据分段处理等[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值