Clion算法竞赛插件AutoCp的配置与使用(附详细图文讲解)
背景
电脑硬盘坏掉了,送到售后修了整整一周(被迫戒了一周的网瘾),换了块硬盘还彻底丢了数据,在纠结用Sublime和VsCode的时候想看看Clion有没有啥合适的插件,最终发现了Auto CP,并放弃了其他两个环境的搭建
前言
此前我一直使用的是Sublime的cppfastolympiccoding插件进行竞赛代码的快速判题(队友强力推荐的jiangly-like开发环境),此后队里还有使用VsCode写竞赛代码借助CPH插件快速判题的成员,使用体验基本跟Sublime差不多,不过得益于VsCode环境,CPH在UI设计上更胜一筹,但本文重点不在于比对这两个环境,所以不对这两个开发环境进行大量的横向对比,我们将重点放在Clion与其他两个的对比上
先说一下Clion下使用Auto CP相较于Sublime和VsCode以及其他C++ IDE的优点:
- 几乎所有XCPC赛事都会提供Clion,在熟悉竞赛环境方面Clion的优势很大
- Clion是目前几乎最完整的C++开发环境,相较于其他C++ IDE而言Visual Studio对C++标准支持的不是很好,Code::Blocks现代化程度不高,devc++算彻底的老古董了,Sublime和VsCode不是彻底的C++ IDE,需要安装大量插件,配置起来相当麻烦
- Clion的调试功能简单好用,可以很方便地找到代码RE的原因
缺点当然也是要提一下的:
- Clion内存占用极高
- 有大量竞赛用不上的功能
(对于非竞赛选手而言倒算不上缺点) - 因资源占用高导致移动端续航相较于其他轻量级的代码编辑器更低
- 对代码风格以及变量命名的要求的强制性高于其他IDE/编辑器(劝退喜欢压行的OI-style代码,将会面对满屏幕的黄色波浪线)
我将从Clion的安装开始介绍,如果你已经安装好了Clion就不需要从Clion安装部分开始看了(太冗长了),可以直接跳到下载插件部分
安装Clion
在JetBrains官网可以下载Clion安装包


下载完成后直接打开,打开过程比较慢,请耐心等待
打开后点击下一步

大家根据自己情况选择安装路径,这里我就不改了

这边建议把这三项打开,文件关联不用动(一般用非项目方式打开的cpp文件也跑不了,还不如不关联)


安装完之后重启即可(其实不重启也不影响)


初始化Clion
Clion第一次打开会让你选择语言,当然直接选择中文即可

然后统一一下用户条款

数据共享大家根据自己的隐私情况选择

这里假定大家没有Clion的许可证,Clion在2025年开放了非商业免费使用,大家可以直接免费非商业使用,有教育邮箱的话可以去申请教育免费许可证,这里不过多赘述

后续的注册及登录流程不过多赘述
安装MinGW
Clion是自带MinGW的,但是不在环境变量里面,为了保证插件的兼容性,我们需要手动为MinGW配置环境变量
右键桌面上的 Clion 点击 打开文件位置

右键桌面上的 此电脑 点击属性

找到高级系统设置

在弹出的窗口中点击 环境变量

在 系统变量 中找到 Path 选项,并点击 编辑

返回刚刚右击Clion后弹出的文件夹窗口,依次点击mingw->bin,然后复制路径

在 编辑环境变量 页面,点击 新建,粘贴复制过去的路径,并点击确定

Clion的基本使用
在获得使用许可后,会进入Clion的欢迎界面,不过不少算法竞赛选手都对项目没有概念,这里顺便介绍一下基本的使用,这里完全面向曾经只使用devc++或VsCode对单一的cpp文件进行编辑,对软件项目没有概念的哪些读者。而有JetBrains IDE使用经验或对软件开发有基础了解的读者可以跳过本节
首先新建一个项目,JetBrains的cpp代码必须在项目中才能运行

然后选择项目的路径及C++标准,OI选手建议C++14,ACM选手建议C++17及以上
一定要选择一个空文件夹,项目一般都是以文件夹为单位进行组织的

接着弹出了项目向导窗口,Clion自带了MinGW,这里直接点击确定即可

然后就可以编写代码了,双击左侧的main.cpp,点击上方的绿色播放键可以运行代码,虫型的按钮可以调试代码

现在编写A+B Problem的代码(如下)进行测试
#include <iostream>
using namespace std;
int main() {
int a,b;
cin>>a>>b;
cout<<a + b<<endl;
return 0;
}
将main.cpp的内容替换为以上内容,点击运行键,将在下方弹出shell窗口,可以在这里进行标准输入

如果你的代码是手写出来的,一定会注意到Clion有自带的AI插件,对你的下一步代码进行提示(干扰) (辅助作弊),因此强烈建议关闭AI插件,关闭方式如下:
在左上角打开菜单:

然后打开设置

打开 插件 栏,进行如下操作

然后重启Clion

以上步骤将在后文中简化为文件->设置->插件->已安装
下载插件
到这里,大家已经对Clion的使用有了基本的概念了,但是使用运行+控制台输入的方式进行调试,效率相对较低,所以我们安装Auto CP插件及competitive companion浏览器插件,实现高效的数据获取及自动比对
我在这里提供两种安装方法,笔者使用的是在Github下载最新插件并本地安装(截至2025/7/31,插件市场的版本并不支持对拍)
直接在插件市场安装
我在写这个教程的时候,最新版的AutoCp(支持对拍)并没有同步更新至插件市场,请大家看清楚插件版本进行选择,插件市场的版本要是在8.0+可以直接在插件市场下载
可以直接在Clion的插件市场安装Auto CP插件,因提供的Auto CP插件版本较旧,不建议在这里进行安装,后文将讲解如何在Github下载最新版插件
在文件->设置->插件->MarketPlace搜索Auto CP后直接点击安装即可

在github获取最新版插件并手动安装
访问插件的github主页
进入Release页面:


点击下载插件后,在文件->设置->插件界面,点击齿轮,从磁盘安装插件,从本地选择刚刚下载的压缩包进行安装

随后就可以在右侧看到插件的图标了

在安装完插件后一定要重启Clion
Competitive Companion安装
在Competitive Companion下载地址(chrome应用商店)为浏览器安装扩展,以便为AutoCp获取竞赛的测试样例
无法打开chrome应用商店的读者可以使用国内镜像站Competitive Companion下载地址(chrome国内镜像站)
安装后会在浏览器插件栏显示,建议固定到地址栏旁边方便使用

使用Auto Cp进行判题
前面用大量的篇幅介绍了怎么安装Clion、安装Auto Cp,安装Competitive Companion,接下来该讲述怎么使用Auto Cp做题了
首先打开一道CF题目(或者其他OJ平台都可以)Codeforces题目链接,我们点击固定在地址栏的 Competitive Companion图标
接着返回Clion,可以看到弹出了一个窗口,我们直接点击确定

我们注意到,AutoCp为我们新建了一个源文件,同时左侧有新建的文件夹

第一次使用这个插件,必须使用右键->运行->题目名来运行(可能是因为Bug,博主第一次使用快捷键会报错,在手动运行一次后就可以使用快捷键了),之后就可以使用快捷键Alt + X进行调试了

评测结果将在下面显示,如果评测结果正确将显示如下:

如果有错误的测试点,将显示如下:

将下方的控制台窗口滚动至底层,可以看到一个<点击以查看差异>的超链接,点击后可以将我们的输出与测试样例输出进行一个直观的对比:

要编辑测试点,可以打开右侧的插件栏

此外,Auto Cp支持使用Competitive Companion对整个竞赛进行解析,只需要我们在题目页点击Competitive Companion的按钮:

之后Auto Cp将会创建所有比赛的源码模板以及获取测试点:

点击确定即可,用法同上
编辑代码模板
Auto Cp对每个题自动生成的模板,可能让不少人对此并不满意,当然模板是可以自定义的
打开菜单->文件->设置->编辑器->文件和代码模板->其他->AutoCp Templates->CP_TEMPLATE_CPP.cpp就可以看到AutoCp默认提供的C++模板如下:
// ${PROBLEM_NAME}
#[[#include]]#<bits/stdc++.h>
using namespace std;
int main() {
$END
return 0;
}
因为#在JetBrains的模板体系里面有特殊用途,所以涉及到#的cpp代码使用了#[[#include]]#进行转义
除#外,注释里的${PROBLEM_NAME}是模板生成时根据编译器环境自动填充的常量,常量表如下:
以下是Auto Cp插件提供的常量
| 常量 | 内容 |
|---|---|
${PROBLEM_GROUP_NAME} |
竞赛名称 |
${PROBLEM_NAME} |
当前源文件对应的问题名 |
${ONLINE_JUDGE_NAME} |
当前源文件对应的OJ名 |
以下是JetBrains提供的常量:
| 常量 | 内容 |
|---|---|
${CALL_SUPER} |
覆盖生成期间的基本函数调用签名 |
${DATE} |
当前系统日期 |
${DAY} |
当前日期 |
${DEFAULT_RETURN_VALUE} |
函数的默认返回值 |
${DIR_PATH} |
新文件所在目录的路径(相对于项目根目录) |
${DS}|美元符号 $。 该变量用于转义美元符号,使其不被视为模板变量的前缀。 |
|
${FILE_NAME} |
新建 C 或 C++ 文件的名称 |
${HEADER_COMMENTS} |
始终返回 true ,用于测试目的 |
${HEADER_FILENAME} |
为类或源文件生成的头文件名称 |
${HOUR} |
当前小时 |
${INCLUDE_GUARD} |
防止重复包含特定头文件 |
${MINUTE} |
当前分钟 |
${SECOND} |
当前秒 |
${MONTH} |
当前月份 |
${MONTH_NAME_FULL} |
当前月份的全名(如一月、二月等) |
${MONTH_NAME_SHORT} |
当前月份名称的前三个字母(如 Jan、Feb 等) |
${NAME} |
新实体的名称(文件、类、接口等) |
${NAMESPACE_CLOSE} |
重构期间创建的命名空间块的结束 |
${NAMESPACE_OPEN} |
重构期间创建的命名空间块的开始 |
${PRODUCT_NAME} |
IDE 名称(例如,CLion) |
${PROJECT_NAME} |
当前项目名称 |
${RETURN_TYPE} |
函数返回值的类型(用于生成新函数) |
${SUIT_NAME} |
Google 测试套件名称 |
${TEST_NAME} |
Google 测试名称 |
${TIME} |
当前系统时间 |
${USER} |
当前用户的登录名(所有平台) |
${USER_NAME} |
对于 Windows 和 Linux:当前用户的登录名 对于 macOS:用户注册的全名 |
${YEAR} |
当前年份 |
JetBrains还提供了更复杂的模板语法,在此不过多赘述,我将我使用的模板分享出来:
// ${ONLINE_JUDGE_NAME} contest ${PROBLEM_GROUP_NAME} ${PROBLEM_NAME}
// Created at ${DAY}.${MONTH}.${YEAR} ${HOUR}:${MINUTE}:${SECOND} in file ${FILE_NAME}
// By ${USER}
#[[#include]]#<iostream>
#[[#include]]#<vector>
#[[#include]]#<algorithm>
#[[#include]]#<cstdlib>
#[[#include]]#<cassert>
#[[#include]]#<iomanip>
#[[#include]]#<climits>
#[[#include]]#<functional>
#[[#include]]#<numeric>
#[[#define]]# ENDL endl
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128;
using u128 = unsigned __int128;
std::istream& CIN = std::cin;
std::ostream& COUT = std::cout;
using namespace std;
const int MOD = 1e9+7;
void solve(){
$END
}
int main() {
int tt = 1;
cin.tie(nullptr);
cin.sync_with_stdio(false);
cout.tie(nullptr);
cout.sync_with_stdio(false);
cin>>tt;
//freopen("case1.in","r",stdin);
//freopen("case1.out","w",stdout);
while(tt--){
solve();
}
return 0;
}
使用Auto Cp对代码进行对拍
Auto Cp自带的对拍器,可以让我们很方便的生成测试数据,对当前代码进行压力测试,这个是Auto Cp相较于cppfastolympiccoding和cph插件最大的独特之处
我们先来讲解不需要Checker的情况下该怎么使用这个对拍
假如我们对一个A + B Problem进行对拍:
题目描述:
输入两个整数A和B,输出A + B的值
输入格式:
对于每组测试样例,输入两个整数\(A,B(1 \leq A \leq 10^{12},1 \leq B \leq 10^{12}\)
输出格式:
对于每组测试样例,输出1个整数,代表两数相加的结果
输入样例1:
1 2
输出样例1:
3
这是一道最经典的用于测试OnlineJudge输入输出功能的题目,接下来我们先给出会被Hack的解法,这个解法是在A+B.cpp文件里面写的,我们的目标是通过对拍找到这个解法的错误之处:
#include <iostream>
using namespace std;
int main(){
int a,b;
cin>>a>>b;
cout<<a+b<<endl;
return 0;
}
Auto Cp会自动在每次运行对拍器时输入一个整数,代表现在是第几次的代码压力测试,我们可以借助这个整数作为随机数生成种子
根据题目测试样例,我们需要相应的使用随机数生成数据,在此我们借助mt19937随机数生成器进行数据生成,答案使用标准输出即可
#include <iostream>
#include <random>
using namespace std;
int main(){
int n;
cin>>n;
mt19937_64 rand(n);
long long a = rand() % (long long)1e12 + 1;
long long b = rand() % (long long)1e12 + 1;
cout<<a<<' '<<b<<endl;
}
接着我们还需要另一个可以写出来的任意解法,这个任意解法不受时间和空间限制,换而言之我们使用这个任意解法生成正确数据,并通过与原程序的输出进行对比,来判断程序的正确性
当然A + B这个问题,我也没什么其他解法了,上述程序无法AC的原因很明显,没有开long long,但我们讨论的问题是,如何生成正确答案,我无法给出其他任意解法,直接放正解作为对拍的数据生成器了
#include <iostream>
using namespace std;
int main(){
long long a,b;
cin>>a>>b;
cout<<a+b<<endl;
return 0;
}
我们现在准备好了数据生成代码和不受时间和空间限制的一个解法,接着我们把他们分别放进插件菜单栏->Generetor->Generator program code和插件菜单栏->Generetor->Solution program code里

在跑到第一个失败样例后,将会出现错误提示,并给出测试数据内容:

假定我们找到代码的错误原因,并通过修改得到了正解,再执行压力测试,将会得到以下结果:

接着是需要Checker的情况下,该怎么编写这个checker
假如我们有这么一道简单的构造题:
题目描述:
构造一个长度为\(n\)的数组\(a\):
- 数组中任意两个数字的最大公约数为1
- 数组中没有重复元素
输入格式:
对于每组测试样例,输入一个整数\(n(1 \leq n \leq 10^4)\)
输出格式:
对于每组测试样例,输出\(n\)个整数,代表构造出来的数组
输入样例1:
5
输出样例1:
2 3 5 7 11
这道题的思路相当简单,只需要构建一个全质数的序列就可以了, 但是如果有参赛选手不愿构造从2开头的质数序列,使用类似3 5 11 17 2的输出,我们也不能将其判错,这时候就需要checker了
要判断选手的输出是否正确其实很简单,只要模拟一遍题意,看是否存在两数gcd不为1即可
我们先思考,要评测一个题目,至少需要哪些输入和输出
- 测试点原输入内容,因为这些内容可能包含数组大小等信息
- 测试代码的输出内容,要判断这个输出是否正确,肯定少不了这个内容
可能需要的内容: - 程序正解的输出内容
需要Checker提供的内容 - 检查后的结果正确与否
在知道Checker需要与哪些内容打交道后,我们将Auto Cp的Checker体系融入: - 测试点原输入内容在:input.txt
- 测试代码的输出内容在:answer.txt
- 程序正解的输出内容在:correct.txt
- 检查后的结果正确与否在:return,答案错误返回1,正确返回0
过去相比有不少算法竞赛选手使用freopen函数,来借助标准输入输出流避免直接和文件打交道,但这个Checker需要跟四个文件打交道,所以freopen函数我个人是不建议使用的
我将直接使用fstream流从文件读取和输出
那么,我们从上面提供的文件实现判题思路如下:
#include <fstream>
#include <numeric>
#include <vector>
using namespace std;
int main()
{
ifstream input("input.txt");
ifstream answer("answer.txt");
ifstream correct("correct.txt");
ofstream comment("comment.txt");
int n;
input>>n;
vector<int> a(n);
for(int i=0;i<n;i++)
{
answer>>a[i];
}
for (int i = 0;i<n;i++)
{
for (int j = i+1;j<n;j++)
{
if (gcd(a[i],a[j]) != 1)
{
return 1;
}
}
}
return 0;
}
将以上代码填入插件菜单栏->Judge->Judge program code中

同时提供生成器和正解:
#include <iostream>
#include <random>
using namespace std;
int main(){
int n;
cin>>n;
mt19937_64 rand(n);
int nn = rand() % int(1e4);
cout<<nn<<endl;
}
#include <iostream>
#include <vector>
using namespace std;
std::vector<int> minp, primes;
void sieve(int n) {
minp.assign(n + 1, 0);
primes.clear();
for (int i = 2; i <= n; i++) {
if (minp[i] == 0) {
minp[i] = i;
primes.push_back(i);
}
for (auto p : primes) {
if (i * p > n) {
break;
}
minp[i * p] = p;
if (p == minp[i]) {
break;
}
}
}
}
int main(){
int n;
cin>>n;
sieve(4e5);
for(int i = 0;i<n;i++){
cout<<primes[i]<<' ';
}
cout<<endl;
return 0;
}
以及我提供的,用户的意料之外的解法,从3开始输出质数,而不是正解所提供的2开始:
#include <iostream>
#include <vector>
using namespace std;
std::vector<int> minp, primes;
void sieve(int n) {
minp.assign(n + 1, 0);
primes.clear();
for (int i = 2; i <= n; i++) {
if (minp[i] == 0) {
minp[i] = i;
primes.push_back(i);
}
for (auto p : primes) {
if (i * p > n) {
break;
}
minp[i * p] = p;
if (p == minp[i]) {
break;
}
}
}
}
int main(){
int n;
cin>>n;
sieve(4e5);
for(int i = 1;i<=n;i++){
cout<<primes[i]<<' ';
}
cout<<endl;
return 0;
}
按下Alt + Shift + X开始进行压力测试,最终用户的不被期望的解如果通过测试,将得到以下内容:

如果没有通过测试,将会得到以下反馈:

至于交互题?我还是绿名蒟蒻,交互题该怎么使用这个插件就靠大家自己研究了(逃

浙公网安备 33010602011771号