首页 > 其他分享 >洛谷与 Codeforces 的难度评级

洛谷与 Codeforces 的难度评级

时间:2023-04-10 22:24:55浏览次数:78  
标签:洛谷 Codeforces CF json print import range 难度

为了比较 CF 与洛谷的题目难度评级,我写了一个爬虫,爬取了 CF 题目在源站和洛谷中的难度,并进行比较。

这里先给出两者的换算:

洛谷 入门 普及- 普及/提高- 普及+/提高 提高+/省选- 省选/NOI- NOI/NOI+/CTSC
CF 800 900-1100 1200-1500 1600-1900 2000-2300 2400-2900 3000-3500

本文中的爬虫代码修改自阮行止的博文《洛谷提交记录爬虫》,已获得作者授权。

获取洛谷的难度评级

我选择按页爬取洛谷的 CF 题库。查看源代码后发现貌似并没有我们想要的题目难度数据。其实它藏在那段 js 后面。

利用 beautifulsoup,我们可以得到 js 里面的数据。

想要深入探究的读者可以参考上面给出的文章链接。这里直接给出源代码,不再赘述。

import requests as rq
from urllib.parse import unquote
from bs4 import BeautifulSoup
from re import findall
import json
import threading

count = 164
lim = 30
l = {}

def getPage(page):
    url = f'https://www.luogu.com.cn/problem/list?type=CF&page={page}'
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
    }
    r = rq.get(url, headers=headers, timeout = 5)
    soup = BeautifulSoup(r.text, 'html.parser')
    res = soup.script.get_text()
    res = unquote(res.split('\"')[1])

    data = json.loads(res)
    data = data['currentData']['problems']['result']
    
    for i in data:
        l[i['pid'][2:]] = i['difficulty']
    
    print(page)

def work(x):
    for i in range(x, x+lim):
        if i > count:
            return
        getPage(i)

if __name__ == '__main__':
    pool = [threading.Thread(target=work, args=[x]) for x in range(1, count + lim, lim)]
    
    for x in pool:
        x.start()
    for x in pool:
        x.join()
        
    json.dump(l, open('luogu.json', 'w'))

获取 CF 的难度评级

Codeforces API 中我们发现有一个 包含所有题目的网页(JSON 格式,大小较大)。因此只需把它保存下来(代码中命名为 codeforces_raw.json),在本地进行处理即可:

import json

raw = json.load(open('codeforces_raw.json', encoding='utf-8'))
l = {}

for i in raw['result']['problems']:
    try:
        l[str(i['contestId']) + i['index']] = i['rating']
    except KeyError:
        print(i)

json.dump(l, open('codeforces.json', 'w'))

汇总

我们再写一个程序,输出具有特定 CF 和洛谷评级的题目个数:

import json

l = json.load(open('luogu.json'))
c = json.load(open('codeforces.json'))

t = {(i, j): [] for i in range(800, 3500+100, 100) for j in range(0, 8)}

for p in l:
    if p not in c:
        continue

    r = c[p]
    d = l[p]
    t[r, d].append(p)

print(end='\t')
for j in range(0, 8):
    print(j, end='\t')
print()

for i in range(800, 3500+100, 100):
    print(i, end='\t')
    for j in range(0, 8):
        print(len(t[i, j]), end='\t')
    print()

输出如下:

	0	1	2	3	4	5	6	7	
800	58	398	197	12	0	0	0	0	
900	10	96	126	21	2	0	0	0	
1000	18	74	178	32	2	0	0	0	
1100	31	41	177	51	5	0	0	0	
1200	38	27	127	129	14	6	0	0	
1300	50	14	91	154	23	10	0	0	
1400	42	4	61	182	29	10	0	0	
1500	48	5	20	194	72	33	1	0	
1600	65	3	18	114	135	63	7	0	
1700	59	5	18	72	163	61	13	0	
1800	49	1	8	37	179	77	13	0	
1900	53	7	5	19	131	128	42	0	
2000	58	4	10	12	97	148	54	0	
2100	55	1	0	4	55	151	72	0	
2200	56	1	2	3	26	167	107	1	
2300	49	0	0	1	7	141	100	3	
2400	46	0	1	2	4	88	214	3	
2500	47	0	0	0	2	50	212	4	
2600	33	0	0	0	1	22	178	22	
2700	32	0	0	0	0	8	170	26	
2800	23	0	0	0	0	5	119	32	
2900	20	0	0	0	0	1	100	50	
3000	30	0	0	0	0	2	40	69	
3100	29	0	0	0	0	0	28	59	
3200	23	0	0	0	0	0	14	70	
3300	10	0	0	0	0	0	6	76	
3400	8	0	0	0	0	0	2	55	
3500	3	0	0	0	0	0	1	108	

其中左边为 CF 评级,上方为洛谷评级,从左到右为:暂无评定,入门,普及-,普及/提高-,普及+/提高,提高+/省选-,省选/NOI-,NOI/NOI+/CTSC。

接下来把表格复制到 Excel 中进行处理。下面是结果:左上角是原始数据;右上角是已知 CF 评级,洛谷评级的出现频率;左下角为已知洛谷评级,CF 评级的出现频率。

标签:洛谷,Codeforces,CF,json,print,import,range,难度
From: https://www.cnblogs.com/dingxutong/p/luogu-codeforces-difficulty.html

相关文章

  • Codeforces Round 677 (Div. 3) E. Two Round Dances(数论)
    https://codeforces.com/contest/1433/problem/E题目大意:n个人(n是偶数)跳了两轮舞,每轮舞正好有n/2个人。你的任务是找出n个人跳两轮舞的方法,如果每轮舞正好由n/2个人组成。每个人都应该属于这两种圆舞中的一种。人相同位置不同也算是同一种方案。input2output1input......
  • Codeforces Round 864 (Div. 2)
    题解报告基本的一些理解和问题都在注释中A:LiHuaandMaze就是判断把其中一个点围起来所需要的最小的格子,考虑下边界的情况就行了#include<bits/stdc++.h>usingnamespacestd;intmain(void){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);intT;c......
  • Codeforces Round 864 (Div. 2) E. Li Hua and Array
    CodeforcesRound864(Div.2E.LiHuaandArray)(暴力修改线段树+lca和数论的结合)Exampleinput5481637215234113234output1021Solution首先你得知道什么是欧拉函数我们\(O(n)\)求出\([1,5e6]\)范围内的每个数的欧拉函数后可以求一下最大的跳......
  • Codeforces Round 863 (Div. 3)
    题解报告基本的一些理解和问题都在注释中A:InsertDigit找到第一个小于输入数字的数的位置塞进去就好了,可以细推,但是粗略想想也能知道#include<bits/stdc++.h>usingnamespacestd;intmain(void){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int......
  • Codeforces Round 865 (Div. 2)
    CodeforcesRound865(Div.2)A.IanVisitsMaryvoidsolve(){intx=read(),y=read();if(__gcd(y,x)!=1){cout<<2<<endl;cout<<1<<""<<y-1<<endl;cout<<x<<"&q......
  • Codeforces Round 864 (Div. 2) C和D
    比赛地址C.LiHuaandChess题意:给出一个棋盘长宽n,m,有一颗棋子在棋盘上,向八个方向走一步的路程代价都为1,现在进行最多3次询问,问能否确认棋子的位置Solution第一次做交互题,想很好想,先询问(1,1),得到x,再询问(1+x,1+x),得到y,最后询问(1+x,1+x-y),如果得到的是0,则输出这个点,反之输......
  • Codeforces Round 860 (Div. 2)
    CodeforcesRound860(Div.2)Date:04/08/2023Link:CodeforcesRound860(Div.2)A|ShowstopperBrief:两组数\(\{a_i\}\)和\(\{b_i\}\),长度都为\(n\).\(\foralli\),可以交换\(a_i\)和\(b_i\),问是否可以使得\(a_n=\max(a_i)\),\(b_n=\max(b_i......
  • Codeforces Round 864 (Div. 2)
    评价:A~E感觉出的挺一般,特别是D怎么放这种暴力题,场上我还没调出来,F没看。但是Orzrui_er。A在一个点周围放障碍即可。B求出最少需要的操作次数\(p\),若\(p>k\)就无解,否则若\(n\)为偶数只能任选一个格子翻偶数次,即有解当且仅当\(2\mid(k-p)\);若\(n\)为奇数可......
  • 洛谷P1308统计单词数,strtok函数的使用以及对于单词分割的一些思考
    [NOIP2011普及组]统计单词数题目描述一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数。现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置。注意......
  • Edu Round 板刷计划 4. Educational Codeforces Round 4 题解
    ChangeLog:2023.04.06开坑.A-TheTextSplitting弱智题.枚举分出来多少个长度为\(p\)的串,则能计算出长度为\(q\)的串有多少个,若合法则直接输出即可.无解输出-1.Samplesubmission.B-HDDisOutdatedTechnology比A还弱智.直接记录每个数的位置,然后模拟一......