CCF精英赛算法题目
A完美金字塔
古埃及的法老现在要为他自己修一座巨大的金字塔,为了使金字塔永存他从世界各地找来了各种各样的石头,每种石头都能够预防特定的灾害。现在我们给每种石头一个编号,使得所有石头的编号都等于下一层压着的石头编号之和,例如以下金字塔:
1 |
|
换句话来说,我们规定最底层的石头编号为 1,之后每层均由下层从左右两端同时向中间合并得到,合并后新石头的编号为合并前石头编号总和,可能会出现如下情况:

(在第四种情况中,编号3的石头视为压着3个编号1的石头)
现在想知道,指定编号的石头的总数各有多少个?
输入输出格式
输入格式:
- 第一行输入两个整数 n 和 m,分别表示最底层的石头数量 和 询问次数
- 接下来 m 个整数,每个整数表示询问的石头编号
输出格式:
- 输出 m 个整数,表示每次询问对应石头的总数
输入输出样例
输入样例1:
1 |
|
输出样例1:
1 |
|
样例1解释:
如下图最底层的10块石头都为1,按照以上规则进行两两合并,得到5个2 。再往上一层由于合并是从最左和最右开始的,所以先合出边缘的2个4,然后中间还剩一个2 。 最后3个合成一个 10 。
1 |
|
测试点
共20个测试点。
时间限制2s,空间限制128MiB。
数据范围:$1≤n≤10{15},1≤m≤106 $
1 |
|
B 两端对齐
小明最近在用软件写文档时发现,在英文内容的键入时,软件会自动添加一些额外的空格到内容中,使得整段英文在文本区域的两端对齐,并且不会出现单个单词被拆分到两行的情况,看上去整齐又美观。
现在给定一篇文章中的n个单词,请试着将其按顺序以“两端对齐”的方式输出,要求:
- 单词间至少由一个空格隔开,行末单词后无空格
- 各行字符数均为m个,必要时可以在单词间补充额外的空格
- 一行内单词间的空格数要尽量相同,若始终不能均匀分配,那么左侧的空格数可以多一些
- 输出行数要尽可能少一些,也即每行放置的单词要尽可能多一些
- 最后一行要左对齐,单词间不再插入额外的空格,末尾补空格至m个字符
输入输出格式
输入格式:
- 第一行输入两个数n、m
- 接下来n行,每行1个单词
,均由小写字母构成
输出格式:
- 输出排版后的文章(数据保证有解)
输入输出样例
输入样例:
1 |
|
输出样例:
1 |
|
样例说明:
第1行在前两个单词后分别额外添加了一个空格; 第2行在第一个单词后额外添加了一个空格; 最后一行在末尾额外添加了4个
空格。 各行均为14个字符,输出的换行符不算入m。
测试点
20个测试点。
每个测试点时间限制2s,内存限制128MiB。
1 |
|
C 光线折射
有一个小房间,光线从左下角沿45度角射入,问k次折射后的位置。
注:正好射向房间一角的话,光线会沿原路反射回去。
输入输出格式
输入格式:
- 第一行输入 n、m、k,分别表示房间大小和折射次数
输出格式:
- 输出光线在第k次折射后停留的坐标
输入输出样例
输入样例1:
1 |
|
输出样例1:
1 |
|
样例1解释:

如图,光线行进路线为OBCD。
测试点
共20个测试点
时间限制1s,空间限制128MiB。
数据范围:
1 |
|
D 根号拆分
在数学上,若a∗a=b的话,那么可以记为
在根号运算中,
现在希望知道的是,给定一个数x,将其拆分为
输入输出格式
输入格式:
- 第一行输入一个数n,表示询问次数
- 之后n行,每行一个数x*,表示要拆分的数
输出格式:
- 输出n行,每行一个数,表示每个询问拆分后得到的最大的a*
输入输出样例
输入样例:
1 |
|
输出样例:
1 |
|
样例说明:
75=5∗5∗3、81=9∗9∗175=5∗5∗3、81=9∗9∗1
测试点
一共20个测试点
每个测试点时间限制为1s,空间限制为128MiB
1 |
|
G二分图
题目描述
小明在学校的编程课上了解到了关于二分图的相关知识,所谓的二分图是一种特殊的图,图中的所有顶点可以分为两个不相交的集合,而图中的所有边的两个顶点都分属于这两个集合。
换句话来说,二分图是可以进行黑白染色的图,即给图中所有顶点都涂上黑色或者白色,使得每条边的两个端点都异色。
现在小明想知道,对于任意的一个n个顶点m*条边的无向图,通过删去一条边使其变为二分图的方案数是多少?
输入输出格式
输入格式:
- 第一行输入两个数n、m,表示图的顶点数和边数
- 接下来m行,每行两个数x、y,表示一条边(编号1~1~m)
输出格式:
- 第一行输出一个数k,表示答案方案数
- 第二行输出k个数,表示k条边的编号,升序排列
输入输出样例
输入样例:
1 |
|
输出样例:
1 |
|
样例说明:
如图,删去两条黑色边的任意一条(边编号为11、12),均可使图成为二分图。

测试点
一共20个测试点。
每个测试点时间限制为1s,空间限制为128MiB。
1 |
|
J 抢红包
题目描述
巨信软件开发了一个抢红包的功能,群里的每个人点开红包就会获得红包额度的一部分金额。
产品经理提出了抢红包的需求:
- 群里人数为n,则红包的额度设置为2 * n-1。
- 在红包生成的一瞬间,群里每个人就已经被分配了金额,点开红包时获得该金额。
- 处于公平考虑,不能有人获得0金额,也不能让某个人获得n的一半以上的金额。
在投入研发之前,产品经理决定先计算一下,对n个人的群,一共有多少种可行的红包分配方案。
答案可能很大,要对1e9+7求余。
输入输出格式
输入格式:
- 第一行t,表示有t组数据
- 接下来每组数据是一个数字n,表示群的人数
输出格式:
- t行,每行一个数字,表示对n个人的群计算出的可行红包方案
输入输出样例
输入样例1:
1 |
|
输出样例1:
1 |
|
样例1说明:
7分配给4个人,每个人可分配金额x的范围为0<x≤2,共4种排列可能:"1 2 2 2"、"2 1 2 2"、"2 2 1 2"、"2 2 2 1"。
输入样例2:
1 |
|
输出样例1:
1 |
|
样例2说明:
- n=1:1<=x<=0,无法分配
- n=2:1<=x<=1,3额度无法分配给2个人
- n=3:1<=x<=1,5额度无法分配给3个人
输入样例3:
1 |
|
输出样例3:
1 |
|
测试点
共20个测试点。
时间限制1s,内存限制128MiB。
1 |
|