HDU1799——循环多少次?
题目描述
运行代码
#include <iostream>
using namespace std;
const int N = 2005;
int db[N][N];
void dabiao() {
for (int i = 1; i <= 2000; ++i) {
db[1][i] = 0;
db[i][1] = i % 1007;
}
for (int i = 2; i <= 2000; ++i) {
for (int j = 2; j <= i; ++j) {
db[i][j] = (db[i - 1][j] + db[i - 1][j - 1]) % 1007;
}
}
}
int main() {
dabiao();
int t;
cin >> t;
while (t--) {
int m, n;
cin >> m >> n;
cout << db[n][m] <<endl;
}
return 0;
}
代码思路
一、整体思路
- 定义一个二维数组
db
用来存储特定的计算结果。 - 通过函数
dabiao
预先计算并填充二维数组db
的值。 - 读取输入的测试用例数量
t
,对于每个测试用例,读取两个整数m
和n
,并输出db[n][m]
的值。
二、函数分析
-
dabiao
函数- 这个函数的目的是通过两层循环来初始化和填充二维数组
db
。 - 第一层循环
for (int i = 1; i <= 2000; ++i)
遍历数组的行。当i = 1
时,将db[1][i]
设置为 0,这是初始化第一行的值。当i > 1
时,将db[i][1]
设置为i % 1007
,这是初始化第一列的值。 - 第二层循环
for (int i = 2; i <= 2000; ++i)
和for (int j = 2; j <= i; ++j)
用于计算并填充除第一行和第一列之外的其他位置的值。db[i][j] = (db[i - 1][j] + db[i - 1][j - 1]) % 1007
这个公式是根据前一行的对应位置的值来计算当前位置的值,然后对 1007 取模以确保结果在特定范围内。
- 这个函数的目的是通过两层循环来初始化和填充二维数组
-
main
函数- 首先调用
dabiao
函数来预先计算二维数组的值。 - 然后读取输入的测试用例数量
t
。 - 在循环中,对于每个测试用例,读取两个整数
m
和n
,并输出db[n][m]
的值,这个值是在dabiao
函数中预先计算好的。
- 首先调用
HDU1316——多少斐波那契?
题目描述
运行代码
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// 高精度加法
string addStrings(const string& num1, const string& num2) {
string result;
int carry = 0;
int i = num1.length() - 1;
int j = num2.length() - 1;
while (i >= 0 || j >= 0 || carry > 0) {
int sum = carry;
if (i >= 0) sum += num1[i--] - '0';
if (j >= 0) sum += num2[j--] - '0';
carry = sum / 10;
result += to_string(sum % 10);
}
reverse(result.begin(), result.end());
return result;
}
// 比较两个高精度数字字符串
int compareStrings(const string& s1, const string& s2) {
if (s1.length() < s2.length()) return -1;
if (s1.length() > s2.length()) return 1;
for (size_t i = 0; i < s1.length(); ++i) {
if (s1[i] < s2[i]) return -1;
if (s1[i] > s2[i]) return 1;
}
return 0;
}
// 二分查找下界
int findLowerBound(const vector<string>& fibonacciNumbers, const string& target) {
int low = 0;
int high = fibonacciNumbers.size() - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
int cmp = compareStrings(fibonacciNumbers[mid], target);
if (cmp >= 0) high = mid - 1;
else low = mid + 1;
}
return high;
}
// 二分查找上界
int findUpperBound(const vector<string>& fibonacciNumbers, const string& target) {
int low = 0;
int high = fibonacciNumbers.size() - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
int cmp = compareStrings(fibonacciNumbers[mid], target);
if (cmp > 0) high = mid - 1;
else low = mid + 1;
}
return low;
}
int main() {
vector<string> fibonacciNumbers;
fibonacciNumbers.push_back("1");
fibonacciNumbers.push_back("2");
string prev1 = "1";
string prev2 = "2";
string current;
while (true) {
current = addStrings(prev1, prev2);
fibonacciNumbers.push_back(current);
if (current.length() > 100) break;
prev1 = prev2;
prev2 = current;
}
string a, b;
while (cin >> a >> b) {
if (a == "0" && b == "0") break;
int lower = findLowerBound(fibonacciNumbers, a);
int upper = findUpperBound(fibonacciNumbers, b);
cout << upper - lower - 1 << endl;
}
return 0;
}
代码思路
整体思路
- 首先定义了一些函数来进行高精度加法、比较两个高精度数字字符串以及使用二分查找在生成的斐波那契数列中查找特定数字的上下界。
- 在
main
函数中,生成一定范围内的斐波那契数列并存储在vector<string>
中。 - 从输入读取两个数字范围
a
和b
,通过查找斐波那契数列中对应于a
和b
的上下界,计算出在该范围内的斐波那契数的数量并输出。
二、函数分析
-
addStrings
函数- 这个函数实现了高精度加法。它从两个字符串表示的数字的末尾开始逐位相加,同时处理进位。
- 通过循环,只要有数字未处理完或者有进位,就继续相加。
- 最后将结果字符串反转后返回,确保高位在左侧。
-
compareStrings
函数- 用于比较两个高精度数字字符串的大小。
- 首先比较字符串长度,如果长度不同,长度长的数字较大。
- 如果长度相同,则逐位比较字符,一旦发现不同的字符,就根据其大小关系返回结果。如果所有字符都相同,则返回相等。
-
findLowerBound
和findUpperBound
函数- 这两个函数都是使用二分查找在给定的斐波那契数列中查找特定数字的上下界。
- 在二分查找过程中,通过比较中间元素与目标数字的大小关系来调整查找区间。
- 如果中间元素大于等于目标数字,则在左半区间继续查找(下界)或调整上界(上界);如果中间元素小于目标数字,则在右半区间继续查找(下界)或调整下界(上界)。
三、主程序流程
-
生成斐波那契数列:从初始的两个斐波那契数 “1” 和 “2” 开始,通过不断调用
addStrings
函数生成后续的斐波那契数,直到生成的数字长度超过 100 为止,并将这些数字存储在vector<string>
中。 -
处理输入:从标准输入读取两个字符串
a
和b
,代表数字范围。如果a
和b
都为 “0”,则结束程序。对于每个输入的范围,将字符串a
和b
进行处理,使得高位在左侧,低位在右侧,方便后续的比较和计算。 -
计算范围内的斐波那契数数量:使用
findLowerBound
函数找到大于等于a
的第一个斐波那契数的下标,记为lower
。使用findUpperBound
函数找到大于b
的第一个斐波那契数的下标,记为upper
。范围内的斐波那契数数量为upper - lower - 1
,并输出这个结果。
HDU1715——大菲波数
题目描述
运行代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> add(const vector<int>& a, const vector<int>& b) {
vector<int> result;
int carry = 0;
int i = 0;
while (i < a.size() || i < b.size() || carry > 0) {
int sum = carry;
if (i < a.size()) sum += a[i];
if (i < b.size()) sum += b[i];
result.push_back(sum % 10);
carry = sum / 10;
i++;
}
return result;
}
vector<int> fibonacci(int n) {
if (n == 1 || n == 2) {
return {1};
}
vector<int> a = {1};
vector<int> b = {1};
vector<int> c;
for (int i = 3; i <= n; i++) {
c = add(a, b);
a = b;
b = c;
}
return b;
}
int main() {
int N;
cin >> N;
for (int i = 0; i < N; i++) {
int p;
cin >> p;
vector<int> result = fibonacci(p);
for (int j = result.size() - 1; j >= 0; j--) {
cout << result[j];
}
cout << endl;
}
return 0;
}
代码思路
一、整体思路
- 定义了两个主要函数:
add
用于高精度整数加法,fibonacci
用于计算斐波那契数列的第n
项。 - 在
main
函数中,首先读取输入的测试用例数量N
,然后对于每个测试用例(整数p
),调用fibonacci
函数计算并输出第p
个斐波那契数。
二、函数分析
-
add
函数- 目的是将两个高精度整数相加。
- 初始化结果向量
result
和进位carry
为 0。 - 通过循环,遍历两个输入向量
a
和b
,同时考虑进位情况。 - 对于每一位,计算当前位的和(包括上一位的进位),取和的个位作为当前位结果存入
result
,并更新进位为和除以 10 的商。 - 循环结束后,如果进位不为 0,将进位也加入结果向量。
-
fibonacci
函数- 如果输入的
n
为 1 或 2,直接返回只有一个元素 1 的向量,表示第 1 和第 2 个斐波那契数。 - 对于
n
大于 2 的情况,使用迭代的方法计算斐波那契数。 - 初始化两个向量
a
和b
分别为第 1 和第 2 个斐波那契数。 - 通过循环从第 3 项开始计算,每次将
a
和b
相加得到新的斐波那契数向量c
,然后更新a
为b
,b
为c
。循环结束后,b
存储的就是第n
个斐波那契数。
- 如果输入的
三、主程序流程
- 读取输入的测试用例数量
N
。 - 对于每个测试用例:读取整数
p
。调用fibonacci(p)
计算第p
个斐波那契数,得到一个高精度整数向量。从向量的最后一位开始输出,依次输出每一位数字,得到第p
个斐波那契数的结果。