大模型编程哪家强?(1)KIMI AI
2024-08-12 21:15:06
发布于:浙江
大家看过来吖!
——————————————————————————————————————————————————————————————————————
KIMI:
Kimi是北京月之暗面科技有限公司于2023年10月9日推出的一款智能助手,主要应用场景为专业学术论文的翻译和理解、辅助分析法律问题、快速理解API开发文档等,是全球首个支持输入20万汉字的智能助手产品。 Kimi在二级市场一度复现了ChatGPT“带货能力”的势头,引发了一众“Kimi概念股”狂飙猛涨。
我很好奇:AI的编程能力怎么样呢?于是心血来潮建立了“大模型编程哪家强?”这个系列,在该系列中,我会依次对:
Kimi
讯飞星火sparkdesk ifly code
文心一言
通义千问
天工AI
豆包(字节跳动)
智谱清言
Chat GPT3.5
Chat GPT4.0
进行评测,评选出最强AI!为此我准备了ACGO里各个难度的题目各2道,让AI解答:
以下为KIMI AI的测试结果与数据
第一题:A1.A+B problem(入门)
以下是kimi的回答:
这个问题非常简单。你只需要读取两个整数 a
和 b
,然后输出它们的和。以下是用 C++ 解决这个问题的示例代码:
#include <iostream>
using namespace std;
int main() {
long long a, b;
cin >> a >> b; // 读取两个整数
cout << a + b << endl; // 输出它们的和
return 0;
}
这段代码首先包含了 iostream
头文件,以便使用 cin
和 cout
。然后,它定义了两个 long long
类型的变量 a
和 b
来存储输入的整数,并使用 cin
读取它们。最后,它使用 cout
输出这两个数的和。
结果
第二题:判断闰年(入门):
以下是kimi的回答:
以下是一个使用C++编写的程序,用于判断输入的年份是否是闰年,并按照题目要求输出结果:
#include <iostream>
using namespace std;
int main() {
int year;
cout << "请输入年份: ";
cin >> year; // 读取用户输入的年份
// 判断闰年的逻辑
if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) {
cout << "Y" << endl; // 如果是闰年,输出Y
} else {
cout << "N" << endl; // 如果不是闰年,输出N
}
return 0;
}
这段代码首先包含了iostream
头文件,以便使用输入输出流。然后定义了main
函数,在其中声明了一个整型变量year
来存储用户输入的年份。使用cin
从标准输入读取年份,然后使用条件语句来判断这个年份是否满足闰年的条件。根据判断结果,使用cout
输出相应的结果。如果年份是闰年,输出"Y",否则输出"N"。最后,程序返回0,表示正常结束。
结果:
第三题:多项式输出(普及):
以下是kimi的回答:
以下是一个C++程序,用于按照上述规则输出一元多项式:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n; // 读取多项式的次数
vector<int> coefficients(n + 1); // 存储系数的向量
for (int i = 0; i < n + 1; ++i) {
cin >> coefficients[i]; // 读取系数
}
// 判断最高次项系数的正负,决定输出的符号
bool start_with_negative = coefficients[0] < 0;
if (start_with_negative) {
cout << "-";
coefficients[0] = -coefficients[0]; // 取绝对值
}
// 输出多项式
for (int i = 0; i <= n; ++i) {
if (coefficients[i] != 0) { // 只输出系数不为0的项
if (i != 0) { // 不是最高次项,需要连接符号
if (coefficients[i] > 0) {
cout << "+";
} else {
cout << "-";
}
}
if (coefficients[i] != 1 && coefficients[i] != -1) {
cout << coefficients[i]; // 输出系数,不为1或-1时
}
if (i == n) {
cout << "x"; // 最高次项,直接输出x
} else if (i == 0) {
continue; // 常数项,直接输出系数
} else {
cout << "x^" << (n - i); // 输出指数
}
}
}
return 0;
}
这个程序首先读取多项式的次数n
,然后读取n + 1
个整数作为多项式的系数,并将它们存储在向量coefficients
中。程序会检查最高次项的系数是否为负数,如果是,则在输出时添加负号,并取该系数的绝对值。然后,程序遍历系数数组,按照题目要求的格式输出多项式的每一项。如果系数不为0,则根据系数的正负和是否为1或-1来决定是否输出系数的绝对值。最后,输出指数部分,如果指数为1,则直接输出x
;如果为0,则不输出;否则,输出x^
后跟指数值。
结果:
第四题:道路游戏(提高+/省选-)[多谢童帅_者仇复告诉我这是假橙题]:
以下是kimi的回答:
这个问题是一个典型的动态规划问题。我们需要通过动态规划来找到最优的策略,以最大化小新收集的金币数量,同时考虑到机器人的购买成本和行走次数限制。
以下是解决这个问题的C++代码示例:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 1000;
const int MAXM = 1000;
int n, m, p;
vector<vector<int>> road(MAXN, vector<int>(MAXM));
vector<int> cost(MAXN);
int dp[MAXN][1 + MAXM]; // dp[i][j] 表示在第 i 个工厂购买机器人,行走 j 次后收集的金币数量
int main() {
cin >> n >> m >> p;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> road[i][j];
}
}
for (int i = 0; i < n; ++i) {
cin >> cost[i];
}
// 初始化 dp 数组
for (int i = 0; i < n; ++i) {
dp[i][1] = -cost[i] + road[i][0];
}
// 动态规划填表
for (int j = 1; j < m; ++j) {
for (int i = 0; i < n; ++i) {
int next = (i + 1) % n;
dp[i][j] = dp[next][j - 1] + road[i][j];
}
}
// 计算在每个工厂购买机器人,行走 p 次后收集的金币总数
for (int k = 2; k <= p; ++k) {
for (int i = 0; i < n; ++i) {
for (int j = k; j <= m; j++) {
int next = (i + 1) % n;
dp[i][j] = max(dp[i][j], dp[next][j - 1] + road[i][j] - cost[i]);
}
}
}
// 计算最终结果
int result = 0;
for (int i = 0; i < n; ++i) {
result = max(result, dp[i][m]);
}
cout << result << endl;
return 0;
}
这段代码首先读取输入数据,包括马路上的金币数量、购买机器人的成本以及机器人的行走次数限制。然后,使用动态规划的方法来计算在每个时间单位和每个工厂购买机器人后,按照最优策略收集的金币数量。最后,输出在所有可能的策略中,小新能够收集到的最多金币数量。
请注意,这个问题的解决方案可能需要根据实际的输入数据进行调整和优化。上述代码提供了一个基本的框架,但可能需要进一步的细化和测试以确保其正确性和效率。
结果:
第五题:数方格(普及/提高-)
以下是kimi的回答:
这个问题可以通过简单的数学计算来解决。对于一个给定的矩形区域,其长为 ( n ) 、宽为 ( m ) ,要在这个矩形内构建最大的正方形,其边长 ( a ) 必须小于或等于 ( n ) 和 ( m ) 中的最小值。对于每一个可能的边长 ( a ) ,我们可以从矩形的左边和上边分别减去 ( a ) ,这样就会在矩形的内部形成一个 ( a \times a ) 的正方形。
对于每一个可能的边长 ( a ) ,矩形的左边和上边都可以有 ( a ) 种不同的起始位置来放置这个正方形。因此,对于每一个边长 ( a ) ,都会有 ( a^2 ) 种不同的放置方式。
以下是C++程序的实现:
#include <iostream>
using namespace std;
int main() {
int n, m;
cin >> n >> m; // 读取矩形的长和宽
int count = 0; // 可行方案数
int minSide = min(n, m); // 取长和宽中的较小值
// 计算所有可能的正方形方案数
for (int a = 1; a <= minSide; ++a) {
count += a * a; // 对于每一个边长a,有a*a种放置方式
}
cout << count << endl; // 输出可行方案数
return 0;
}
这段代码首先读取输入的长和宽,然后计算出最小边长,接着通过一个循环来计算所有可能的正方形方案数,最后输出计算结果。这种方法简单且高效,可以快速得到问题的答案。
结果:
第六题:Hanoi 双塔问题(普及/提高-)
以下是kimi的回答:
这个问题实际上是著名的“汉诺塔”问题的一个变种。对于汉诺塔问题,完成移动所需的最少移动次数是 (2^n - 1),其中 (n) 是圆盘的总数。但在这个问题中,我们有 (2n) 个圆盘,每个尺寸的圆盘有两个相同的,且不加区分。因此,我们可以观察到移动次数实际上是 (2^n)。
这是因为,对于 (n) 个不同的圆盘,我们可以将其分为两组,每组有 (n) 个圆盘,且每组中的圆盘大小是相同的。我们可以将这个问题看作是将一组圆盘从 A 移动到 C,而另一组圆盘从 A 移动到 B,然后再从 B 移动到 C。对于每组圆盘,我们需要 (2^{n-1}) 次移动,因为每移动一个圆盘到目标柱,都需要额外移动其他所有圆盘。由于有两组圆盘,总的移动次数就是 (2 \times 2^{n-1} = 2^n)。
以下是C++程序的实现:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n; // 读取圆盘的数量
// 计算并输出完成移动所需的最少移动次数
cout << (1 << n) << endl; // 使用位移操作来计算2的n次方
return 0;
}
这段代码首先读取输入的圆盘数量 (n),然后使用位移操作 1 << n
来计算 (2^n),这是计算幂的一个快速方法,最后输出所需的最少移动次数。这种方法简单且高效,能够快速得到问题的答案。
结果:
第七题:靶型数独(普及+/提高):
以下是kimi的回答:
要解决这个问题,我们需要编写一个C程序,该程序能够解决标准数独问题,并计算给定解决方案的得分。以下是一个简化的C程序示例,它使用回溯法来解决数独问题并计算得分。
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
const int SIZE = 9;
int board[SIZE][SIZE]; // 数独棋盘
int score_board[SIZE][SIZE]; // 分值棋盘
bool solved; // 是否找到解决方案
// 检查是否可以在board[row][col]放置数字num
bool is_valid(int row, int col, int num) {
for (int i = 0; i < SIZE; ++i) {
if (board[row][i] == num || board[i][col] == num) return false;
}
int startRow = row - row % 3;
int startCol = col - col % 3;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (board[startRow + i][startCol + j] == num) return false;
}
}
return true;
}
// 递归函数,尝试填充数独
bool solve_sudoku(int row, int col) {
if (row == SIZE) { // 完成一行后,移动到下一行
return solve_sudoku(0, col + 1);
}
if (col == SIZE) { // 找到解决方案
solved = true;
return true;
}
if (board[row][col] != 0) return solve_sudoku(row + 1, col); // 已填充,跳过
for (int num = 1; num <= SIZE; ++num) {
if (is_valid(row, col, num)) {
board[row][col] = num; // 放置数字
if (solve_sudoku(row + 1, col)) return true; // 递归放置下一个数字
board[row][col] = 0; // 回溯
}
}
return false; // 无法放置任何数字
}
// 计算得分
int calculate_score() {
int total_score = 0;
for (int i = 0; i < SIZE; ++i) {
for (int j = 0; j < SIZE; ++j) {
int distance = min(i, SIZE - i - 1) + min(j, SIZE - j - 1);
int score = (10 - distance) * board[i][j];
total_score += score;
}
}
return total_score;
}
int main() {
// 读取数独棋盘
for (int i = 0; i < SIZE; ++i) {
for (int j = 0; j < SIZE; ++j) {
cin >> board[i][j];
}
}
// 初始化分值棋盘
for (int i = 0; i < SIZE; ++i) {
for (int j = 0; j < SIZE; ++j) {
score_board[i][j] = (10 - min(i, SIZE - i - 1) + min(j, SIZE - j - 1));
}
}
// 解决数独
solved = solve_sudoku(0, 0);
if (!solved) {
cout << -1 << endl;
return 0;
}
// 计算并输出得分
int score = calculate_score();
cout << score << endl;
return 0;
}
这个程序首先定义了一个数独棋盘和分值棋盘,然后使用is_valid
函数来检查是否可以在某个位置放置某个数字。solve_sudoku
函数使用回溯法来解决数独问题。如果找到一个解决方案,calculate_score
函数将根据棋盘上的数字和分值计算得分。如果数独无解,程序将输出-1。
请注意,这个程序假设输入的数独是可解的,并且没有实现任何性能优化或错误检查。在实际应用中,可能需要添加更多的功能和检查来确保程序的健壮性和效率。
结果:
第八题:最优贸易(普及+/提高):
以下是kimi的回答:
这个问题可以通过图论中的算法来解决。我们需要构建一个表示城市和道路的图,然后使用搜索算法(如深度优先搜索或广度优先搜索)来找出所有可能的旅行路径,并计算每条路径上的最大潜在利润。以下是解决这个问题的步骤:
- 读取输入数据,包括城市数量、道路数量、每个城市的商品价格以及每条道路的信息。
- 使用邻接表或邻接矩阵来表示图,存储城市之间的连接关系和通行方向。
- 对于每个城市,使用DFS或BFS搜索从该城市出发的所有可能路径。
- 在搜索过程中,记录每个城市到达时的商品价格,并计算在该城市卖出商品时的潜在利润。
- 比较所有路径上的潜在利润,找出最大值。
由于这个问题的规模可能很大(城市数可达100000,道路数可达500000),因此算法的效率非常重要。以下是C++代码的框架:
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_N = 100000;
const int MAX_M = 500000;
int n, m;
vector<pair<int, int>> edges[MAX_N];
int prices[MAX_N];
int max_profit = 0;
void dfs(int curr_city, int bought_price, int curr_profit) {
if (curr_city == n - 1) { // 到达终点城市
max_profit = max(max_profit, curr_profit);
return;
}
if (bought_price > 0 && curr_profit < prices[curr_city] - bought_price) {
max_profit = max(max_profit, prices[curr_city] - bought_price);
}
for (auto &edge : edges[curr_city]) {
int next_city = edge.first;
int is_bidirectional = edge.second;
if (bought_price <= prices[next_city] && is_bidirectional) {
dfs(next_city, bought_price, curr_profit + (prices[next_city] - bought_price));
}
dfs(next_city, max(bought_price, prices[next_city]), max(curr_profit, prices[next_city] - bought_price));
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; ++i) {
cin >> prices[i];
}
for (int i = 0; i < m; ++i) {
int x, y, z;
cin >> x >> y >> z;
x--; y--; // 将城市编号转换为从0开始
edges[x].emplace_back(y, z);
if (z == 2) {
edges[y].emplace_back(x, z);
}
}
for (int i = 0; i < n; ++i) {
dfs(i, 0, 0);
}
cout << (max_profit > 0 ? max_profit : 0) << endl;
return 0;
}
请注意,这个代码框架是一个起点,它可能需要进一步的优化和调整才能处理大规模数据。特别是,由于问题规模的限制,可能需要使用更高效的图表示和搜索算法。此外,由于DFS可能遇到重复路径的问题,可能需要使用记忆化搜索或动态规划来避免重复计算。
结果:
第九题:函数调用(提高+/省选-)
以下是kimi回答:
这个问题可以通过模拟的方式来解决。我们需要根据输入的函数序列,依次执行每个函数,并记录每个元素的变化。以下是解决这个问题的C++代码示例:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX_N = 20000;
const int MOD = 998244353;
struct Function {
int type;
int index; // 仅类型1有效
int value; // 仅类型1和2有效
vector<int> children; // 仅类型3有效
};
Function functions[MAX_N];
vector<int> data;
vector<int> temp_data;
void apply_add(int index, int value) {
for (int i = 0; i < data.size(); ++i) {
temp_data[i] = (i == index ? (data[i] + value) : data[i]) % MOD;
}
swap(data, temp_data); // 用temp_data覆盖原data
}
void apply_multiply(int value) {
for (int i = 0; i < data.size(); ++i) {
data[i] = data[i] * value % MOD;
}
}
void apply_function(int func_id) {
Function& f = functions[func_id];
switch (f.type) {
case 1:
apply_add(f.index, f.value);
break;
case 2:
apply_multiply(f.value);
break;
case 3:
// 保存当前状态,应用子函数
temp_data = data;
for (int child_id : f.children) {
apply_function(child_id);
}
swap(data, temp_data); // 恢复状态
break;
}
}
int main() {
int n, m, q;
cin >> n;
data.resize(n);
for (int i = 0; i < n; ++i) {
cin >> data[i];
}
cin >> m;
for (int i = 0; i < m; ++i) {
int type, index, value, c;
cin >> type;
functions[i].type = type;
if (type == 1) {
cin >> index >> value;
functions[i].index = index - 1; // 将1-based index转换为0-based
functions[i].value = value;
} else if (type == 2) {
cin >> value;
functions[i].value = value;
} else if (type == 3) {
cin >> c;
for (int j = 0; j < c; ++j) {
int child_id;
cin >> child_id;
functions[i].children.push_back(child_id - 1); // 转换为0-based
}
}
}
cin >> q;
for (int i = 0; i < q; ++i) {
int func_id;
cin >> func_id;
apply_function(func_id - 1); // 转换为0-based
}
// 输出最终结果
for (int i = 0; i < n; ++i) {
cout << data[i] << (i < n - 1 ? " " : "");
}
cout << endl;
return 0;
}
这段代码首先读取输入数据,包括数据的个数、初始值、函数的个数和每个函数的具体信息。然后,根据函数的类型,定义了相应的应用函数:apply_add
、apply_multiply
和apply_function
。在apply_function
中,我们根据函数的类型执行相应的操作,如果是类型3的函数,我们会递归地应用其子函数。
最后,我们读取要执行的函数操作序列长度和序列本身,依次应用每个函数,并输出最终的结果。
请注意,这个解决方案假设输入的函数序列是有效的,并且没有进行错误检查。在实际应用中,可能需要添加更多的功能和检查来确保程序的健壮性和效率。
结果:
第十题:推销员(提高+/省选-)
以下是kimi的回答:
这个问题可以通过动态规划来解决。我们需要维护到当前住户为止的最大疲劳值,并且考虑推销和返回的过程。
以下是解决这个问题的C++代码示例:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX_N = 100000;
int S[MAX_N], A[MAX_N]; // S[i]是住户i到入口的距离,A[i]是推销给住户i积累的疲劳值
vector<int> dp(MAX_N + 1, 0); // dp[i]表示到第i家住户推销产品后的总疲劳值
int main() {
int N;
cin >> N;
for (int i = 0; i < N; ++i) {
cin >> S[i];
}
for (int i = 0; i < N; ++i) {
cin >> A[i];
}
// 初始化dp数组
for (int i = 0; i < N; ++i) {
dp[i + 1] = dp[i] + S[i] * 2 + A[i]; // 到达第i家并推销的疲劳值
}
// 动态规划求解
for (int i = 1; i < N; ++i) {
// 更新dp数组,找到经过i家住户时的最大疲劳值
// 考虑推销i家住户之前的所有住户中,哪一家推销后的疲劳值最大
// 因为推销i家住户后还需要返回,所以用dp[i] - S[i] * 2来计算返回的疲劳值
dp[i] = max(dp[i], dp[i - 1]);
for (int j = i - 1; j >= 0; --j) {
dp[j] = max(dp[j], dp[i] - (S[i] - S[j]) * 2);
}
}
// 输出结果
for (int i = 1; i <= N; ++i) {
cout << dp[i] << endl;
}
return 0;
}
这段代码首先读取输入数据,包括住户的数量、每家住户到入口的距离以及推销产品积累的疲劳值。然后,使用一个dp
数组来存储到每家住户推销产品后的总疲劳值。通过动态规划的方式,我们可以找到经过每家住户时的最大疲劳值,最后输出每个dp[i]
的值作为结果。
请注意,这个解决方案可能需要根据实际的输入数据进行调整和优化。上述代码提供了一个基本的框架,但可能需要进一步的细化和测试以确保其正确性和效率。
结果:
第11题:方差(省选/NOI- NOIP提高组)
以下是kimi的回答:
这个问题实际上是一个数学问题,我们需要找到方差的最小值。由于数列是非严格递增的,我们可以通过以下步骤来找到方差的最小值:
- 计算原始数列的平均值 ( \bar{a} )。
- 由于方差的最小值出现在数列变为等差数列时,我们可以构造一个等差数列,其公差为 ( d ),第一个数为 ( a_1 - (n-1)d ),第 ( i ) 个数为 ( a_i - (n-1-i)d )。
- 由于等差数列的和等于原始数列的和,我们可以建立等式:
[ \frac{n(2a_1 + (n-1)(a_n - a_1))}{2} = n \frac{(a_1 + a_n)}{2} ]
解这个等式得到等差数列的公差 ( d )。 - 使用等差数列的公差 ( d ),计算等差数列的平均值,并计算方差。
以下是C++代码示例:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> a(n);
long long sum = 0;
for (int i = 0; i < n; ++i) {
cin >> a[i];
sum += a[i];
}
// 计算原始数列的平均值
long long average = sum * 2 / n;
// 计算等差数列的公差d
long long d = (2 * average - a[0] - a[n - 1]) / (n - 1);
// 计算等差数列的方差
long long variance = 0;
for (int i = 0; i < n; ++i) {
variance += (a[i] - (average - i * d)) * (a[i] - (average - i * d));
}
variance /= n;
// 输出方差的最小值的n^2倍
cout << variance * n * n << endl;
return 0;
}
这段代码首先读取输入数据,包括数列的长度和数列中的每个元素。然后,计算原始数列的平均值,并构造等差数列来找到方差的最小值。最后,输出方差的最小值乘以 ( n^2 ) 的结果。
请注意,这个解决方案可能需要根据实际的输入数据进行调整和优化。上述代码提供了一个基本的框架,但可能需要进一步的细化和测试以确保其正确性和效率。
结果:
第12题:华容道(省选/NOI- NOIP提高组)
以下是kimi的回答:
这个问题是一个搜索问题,可以通过广度优先搜索(BFS)算法来解决。我们需要为每个查询找到从起始空白格到目标格的最短路径,同时考虑可移动棋子的限制。
以下是解决这个问题的C++代码示例:
#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
using namespace std;
const int MAXN = 30;
const int MAXM = 30;
const int INF = 1e9;
int n, m, q;
vector<vector<int>> board;
bool visited[MAXN][MAXM];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
// 检查是否在棋盘内
bool in_board(int x, int y) {
return x >= 0 && x < n && y >= 0 && y < m;
}
// BFS 搜索空白格到目标格的最短路径
int bfs(int sx, int sy, int tx, int ty) {
queue<pair<int, int>> q;
q.push({sx, sy});
visited[sx][sy] = true;
int steps = 0;
while (!q.empty()) {
int sz = q.size();
for (int i = 0; i < sz; ++i) {
auto p = q.front(); q.pop();
int x = p.first, y = p.second;
if (x == tx && y == ty) return steps; // 找到目标位置
for (int k = 0; k < 4; ++k) {
int nx = x + dx[k], ny = y + dy[k];
if (in_board(nx, ny) && board[nx][ny] == 1 && !visited[nx][ny]) {
q.push({nx, ny});
visited[nx][ny] = true;
}
}
}
steps++;
}
return -1; // 无法到达目标位置
}
int main() {
cin >> n >> m >> q;
board.assign(n, vector<int>(m));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> board[i][j];
}
}
while (q--) {
int ex, ey, sx, sy, tx, ty;
cin >> ex >> ey >> sx >> sy >> tx >> ty;
ex--; ey--; sx--; sy--; tx--; ty--; // 转换为0-based index
// 检查起始位置和目标位置是否为空
if (board[ex][ey] != 1 || board[tx][ty] != 1) {
cout << "-1" << endl;
continue;
}
// 复制棋盘状态,因为BFS会改变visited数组
vector<vector<int>> board_copy = board;
memset(visited, false, sizeof(visited));
int result = bfs(sx, sy, tx, ty);
cout << result << endl;
}
return 0;
}
这段代码首先读取输入数据,包括棋盘的大小、棋盘状态、查询数量以及每个查询的详细信息。然后,对于每个查询,使用BFS算法搜索从空白格到目标格的最短路径。如果找到路径,输出所需的最少时间;如果没有找到路径,输出-1。
请注意,这个解决方案可能需要根据实际的输入数据进行调整和优化。上述代码提供了一个基本的框架,但可能需要进一步的细化和测试以确保其正确性和效率。
结果:
第13题:兔农(NOI/NOI+/CTSC NOI Online)
以下是kimi的回答:
这个问题是一个变种的斐波那契数列问题,其中斐波那契数列的每个数是前两个数的和,但加上了一个条件:如果某个月的兔子对数除以 ( k ) 的余数是 1,那么这个月的兔子对数会减少到 1 对,因为只有一对兔子无法围成圈。
这个问题可以通过动态规划来解决。我们可以定义一个数组 dp[i]
来存储第 ( i ) 个月的兔子对数除以 ( p ) 的余数。初始状态是 dp[1] = 1
和 dp[2] = 1
,因为前两个月都是一对兔子。
对于 ( i > 2 ) 的情况,我们有:
[ dp[i] = (dp[i-1] + dp[i-2]) \mod p ]
但是,如果 ( dp[i] \mod k = 1 ),我们需要将 dp[i]
更新为 1。这意味着我们需要在计算完 ( dp[i] ) 后检查这个条件。
以下是用 C++ 解决这个问题的示例代码:
#include <iostream>
using namespace std;
int main() {
int n, k, p;
cin >> n >> k >> p;
int dp[1001] = {0}; // 假设 n 不会超过 1000
dp[1] = 1;
dp[2] = 1;
for (int i = 3; i <= n; ++i) {
dp[i] = (dp[i-1] + dp[i-2]) % p;
if (dp[i] % k == 1) {
dp[i] = 1;
}
}
cout << dp[n] << endl;
return 0;
}
这段代码首先读取输入的 ( n ),( k ) 和 ( p ),然后初始化一个足够大的数组来存储每个月的兔子对数除以 ( p ) 的余数。接着,它使用一个循环来计算从第三个月到第 ( n ) 个月的兔子对数,并在每次循环结束时检查是否需要将当前月的兔子对数更新为 1。最后,它输出第 ( n ) 个月的兔子对数除以 ( p ) 的余数。
结果:
第14题:Compound Escape--Platinum(NOI/NOI+/CTSC USACO)(全英文题目,略难,给kimi上强度)
以下是kimi的回答:
这个问题是一个组合优化问题,可以通过动态规划来解决。我们需要计算出所有可能的最小成本逃生方案的数量。
首先,我们可以观察到,对于每个单元格,要使所有牛聚集到一个单元格里,我们必须打开到达该单元格的所有门。因此,问题可以转化为:对于每个单元格,计算出到达它的所有可能路径的最小成本,然后计算有多少种不同的路径可以选择。
以下是解决这个问题的步骤:
- 计算每个单元格的最小成本:使用动态规划,从边界开始,逐步计算每个单元格的最小成本。
- 计算每个单元格的逃生方案数量:对于每个单元格,如果它的最小成本路径中有多个门的成本相同,那么这些门可以以任意顺序打开,从而产生不同的方案。
- 计算总的逃生方案数量:对于所有单元格,累加它们的逃生方案数量。
以下是C++代码示例:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MOD = 1e9 + 7;
int n, k;
// 动态规划计算每个单元格的最小成本
void calculate_min_cost(vector<vector<int>>& cost, vector<vector<int>>& min_cost) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < k; ++j) {
int up = (i == 0) ? 1e9 + 7 : min_cost[i - 1][j];
int left = (j == 0) ? 1e9 + 7 : min_cost[i][j - 1];
min_cost[i][j] = min(up, left);
}
}
for (int i = 1; i < n; ++i) {
for (int j = 1; j < k; ++j) {
min_cost[i][j] = min(min_cost[i - 1][j], min_cost[i][j - 1]);
}
}
}
// 计算并输出逃生方案的数量
int count_escape_plans(vector<vector<int>>& cost, vector<vector<int>>& min_cost) {
vector<vector<int>> plans(n, vector<int>(k, 0));
int total_plans = 1;
for (int i = n - 1; i >= 0; --i) {
for (int j = k - 1; j >= 0; --j) {
int current_cost = cost[i][j];
int right_plans = (j == k - 1) ? 1 : plans[i][j + 1];
int down_plans = (i == n - 1) ? 1 : plans[i + 1][j];
if (i > 0 && min_cost[i - 1][j] == min_cost[i][j] + cost[i - 1][j]) {
total_plans = (total_plans * plans[i - 1][j]) % MOD;
}
if (j > 0 && min_cost[i][j - 1] == min_cost[i][j] + cost[i][j - 1]) {
total_plans = (total_plans * plans[i][j - 1]) % MOD;
}
plans[i][j] = (right_plans + down_plans - (i > 0 && j > 0 && cost[i][j] == cost[i - 1][j] && cost[i][j] == cost[i][j - 1] ? 1 : 0)) % MOD;
}
}
return total_plans;
}
int main() {
cin >> n >> k;
vector<vector<int>> cost(k, vector<int>(n, 0));
vector<vector<int>> horizontal_cost(n, vector<int>(k - 1));
vector<vector<int>> vertical_cost(k, vector<int>(n - 1));
vector<vector<int>> min_cost(n, vector<int>(k, 1e9 + 7));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < k - 1; ++j) {
cin >> horizontal_cost[i][j];
cost[i][j] = cost[i][j + 1] = horizontal_cost[i][j];
}
}
for (int i = 0; i < k; ++i) {
for (int j = 0; j < n - 1; ++j) {
cin >> vertical_cost[i][j];
cost[j][i] = cost[j + 1][i] = vertical_cost[i][j];
}
}
calculate_min_cost(cost, min_cost);
int result = count_escape_plans(cost, min_cost);
cout << result << endl;
return 0;
}
这段代码首先读取输入数据,包括网格的大小、每个门的成本。然后,使用动态规划计算每个单元格的最小成本。接着,计算每个单元格的逃生方案数量,并累加得到总的逃生方案数量。最后,输出结果。
请注意,这个解决方案可能需要根据实际的输入数据进行调整和优化。上述代码提供了一个基本的框架,但可能需要进一步的细化和测试以确保其正确性和效率。
结果:
总结:
优点:
1:kimi的速度很快,基本5~6秒就可完成题解。
2:kimi的功底还是很扎实的,基础题几乎都能应付,格式基本没问题。
3:kimi对英文题临危不乱(虽然最后没AC),能读懂英文题。
4:kimi很会解释(虽然几乎都错了)。
缺点:
1:kimi很容易无视输出样例,喜欢按自己的来。
2:kimi的代码极其臃肿,简直不忍直视!
3:kimi很容易理解错误,对c++的理解程度不深。
4:kimi错多对少,题目的难点总是会写错。
结语:
在这个AI盛行的时代,KIMI的强项并不理想,但我们也知道,kimi的能力主要还是在写作上,并不适用于编程,大家自行理解!
kimi正确(1\14)
此文章仅代表个人观点
无意引战
无意抹黑
不喜勿喷
全部评论 7
e,但是有些wa是因为程序在输入之前输出了一个提示语,这个也会算到OUT文件的,所以呢,我建议你先把输入提示语删了再看看
2024-08-18 来自 浙江
0那是kimi没有审题完全的原因,也是它的能力的一部分
2024-08-18 来自 浙江
0有道理,我都没想到
2024-08-18 来自 浙江
0
我觉得快被AC君封了
2024-08-17 来自 浙江
0大模型编程哪家强?cmgpt撞上墙
2024-08-14 来自 广东
0个人觉得讯飞星火更强
2024-08-14 来自 四川
0讯飞星火的各项数据都是遥遥领先😁
2024-08-14 来自 浙江
0对呀
2024-08-14 来自 四川
0
顶
2024-08-13 来自 江苏
0顶
2024-08-14 来自 浙江
0
普及-里面混了个洛谷蓝题(
2024-08-12 来自 湖南
0?哪题呀?
2024-08-12 来自 浙江
0道路游戏的编号是A16
2024-08-12 来自 浙江
0就是道路游戏
2024-08-12 来自 湖南
0
顶
2024-08-12 来自 浙江
0
有帮助,赞一个