2019年第十届蓝桥杯大赛软件类省赛 C/C++ 大学 A 组 题面+题解+部分代码

只是个人赛后写一下自己对题目的感受,并不保证写的对。。当然内心深切的希望我写的都对,不对的也能多混几分`(*>﹏<*)′

 

 

试题 A: 平方和   

本题总分:5 分
【问题描述】 小明对数位中含有 2、0、1、9 的数字很感兴趣,在 1 到 40 中这样的数包 括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574,平方和是 14362。 注意,平方和是指将每个数分别平方后求和。 请问,在 1 到 2019 中,所有这样的数的平方和是多少?
思路:直接for循环枚举每个数,然后特判有没有2019,有就加上,求就可以了。

答案似乎是2658417852

试题 B: 数列求值  

本题总分:5 分
【问题描述】 给定数列 1, 1, 1, 3, 5, 9, 17, …,从第 4 项开始,每项都是前 3 项的和。求 第 20190324 项的最后 4 位数字。
思路:dp[i]=dp[i-1]+dp[i-2]+dp[i-3]%10000,很简单,最后输出dp[20190324]就可以了

答案似乎是4659

试题 C: 最大降雨量   

本题总分:10 分
【问题描述】
由于沙之国长年干旱,法师小明准备施展自己的一个神秘法术来求雨。 这个法术需要用到他手中的 49 张法术符,上面分别写着 1 至 49 这 49 个 数字。法术一共持续 7 周,每天小明都要使用一张法术符,法术符不能重复使 用。 每周,小明施展法术产生的能量为这周 7 张法术符上数字的中位数。法术 施展完 7 周后,求雨将获得成功,降雨量为 7 周能量的中位数。 由于干旱太久,小明希望这次求雨的降雨量尽可能大,请大最大值是多少?

思路:每天的七个数排个序(从左到右,小到大)。再按每天的中位数排序(从上到下,小到大),那么中间位置的[4,4]就会是降雨量,可以比[4,4]小的只能是其上面行和左面的列的数,数一数,

答案:34

试题 D: 迷宫  

本题总分:10 分
【问题描述】 下图给出了一个迷宫的平面图,其中标记为 1 的为障碍,标记为 0 的为可 以通行的地方。
010000

000100

001001

110000
迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这 个它的上、下、左、右四个方向之一。 对于上面的迷宫,从入口开始,可以按DRRURRDDDR 的顺序通过迷宫, 一共 10 步。其中 D、U、L、R 分别表示向下、向上、向左、向右走。 对于下面这个更复杂的迷宫(30 行 50 列),请找出一种通过迷宫的方式, 其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。 请注意在字典序中D

思路:dfs,bfs都可以,只要按照DLRU的顺序访问,就可以了。。

试题 E: RSA 解密  

本题总分:15 分
【问题描述】 RSA 是一种经典的加密算法。它的基本加密过程如下。

首先生成两个质数 p, q,令 n = p·q,设 d 与 (p−1)·(q−1) 互质,则可 找到 e 使得 d·e 除 (p−1)·(q−1) 的余数为 1。

n, d, e 组成了私钥,n, d 组成了公钥。

当使用公钥加密一个整数 X 时(小于 n),计算 C = X^d mod n,则 C 是加 密后的密文。

当收到密文 C 时,可使用私钥解开,计算公式为 X = C^e mod n。 例如,当 p = 5, q = 11, d = 3 时,n = 55, e = 27。 若加密数字 24,得 243 mod 55 = 19。 解密数字 19,得 1927 mod 55 = 24。 现在你知道公钥中 n = 1001733993063167141, d = 212353,同时你截获了 别人发送的密文 C = 20190324,请问,原文是多少?
思路

(一定要吐槽一下)d·e 除 (p−1)·(q−1) 的余数为 1,难道不应该是 (p−1)·(q−1) %d·e=1?除和除以是有区别的?真实逼死数学系学生,一直按着除做,一直除不断,,还以为自己哪里推错了,算了N多遍,还是除不断,放弃啊,还是怪自己没有先算算样例??(虽然即便知道除以,最后也未必能做对,但是因为这个除纠结了好久,无用功,,)

暴力循环找n的因子,就能直接找到pq,n只能分解成一对质因子相乘,而且正好都能与d互质。然后根据(d*e)%( (p−1)·(q−1))=1

枚举商x, ((p−1)·(q−1)*x+1)%d==0时,e=((p−1)·(q−1)*x+1)/d;

然后就算X = C^e mod n,似乎可以用java大数+快速幂。

答案:

579706994112328949

试题 F: 完全二叉树的权值

时间限制: 1.0s 内存限制: 256.0MB 本题总分:15 分
【问题描述】 给定一棵包含 N 个节点的完全二叉树,树上每个节点都有一个权值,按从 上到下、从左到右的顺序依次是 A1, A2, ··· AN,如下图所示:
现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点 权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。 注:根的深度是 1。
【输入格式】
第一行包含一个整数 N。 第二行包含 N 个整数 A1, A2, ··· AN 。
【输出格式】
输出一个整数代表答案。
【样例输入】 7 1 6 5 4 3 2 1
【样例输出】 2
【评测用例规模与约定】 对于所有评测用例,1≤ N ≤100000,−100000≤ Ai ≤100000。
思路:直接从根节点1开始dfs就可以,只需要注意long long和初值负无穷小就可以了。

代码:

#include
using namespace std;
typedef long long ll;
#define mod 1000000000
#define maxn 110000
ll a[maxn],sum[50],ans,x,n;
void dfs(int rt,long long ceng)
{
    if(rt>n) return;
    x=max(x,ceng);
    sum[ceng]+=a[rt];
    dfs(rt*2,ceng+1);
    dfs(rt*2+1,ceng+1);
    return;
}
int main()
{
    int z;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%I64d",&a[i]);
        dfs(1,1);
    ans=-1000000000000000;
    for(int i=1;i<=x;i++)
    {
        if(ans

试题 G: 外卖店优先级

时间限制: 1.0s 内存限制: 256.0MB 本题总分:20 分
【问题描述】 “饱了么”外卖系统中维护着 N 家外卖店,编号 1 ∼ N。每家外卖店都有 一个优先级,初始时 (0 时刻) 优先级都为 0。 每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减 到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。 如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果 优先级小于等于 3,则会被清除出优先缓存。 给定 T 时刻以内的 M 条订单信息,请你计算 T 时刻时有多少外卖店在优 先缓存中。
【输入格式】 第一行包含 3 个整数 N、M 和 T。 以下 M 行每行包含两个整数 ts 和 id,表示 ts 时刻编号 id 的外卖店收到 一个订单。
【输出格式】
输出一个整数代表答案。
【样例输入】 2 6 6 1 1 5 2 3 1 6 2 2 1 6 2
【样例输出】 1
【样例解释】 6 时刻时,1 号店优先级降到 3,被移除出优先缓存;2 号店优先级升到 6, 加入优先缓存。所以是有 1 家店 (2 号) 在优先缓存中。
【评测用例规模与约定】 对于 80% 的评测用例,1≤ N,M,T ≤10000。 对于所有评测用例,1≤ N,M,T ≤100000,1≤ts≤T,1≤id ≤ N。
思路:这个题,可能做的太快?粗心了,,忽略了<=3才除名。。只算了>5的情况。。有点凉呀。。

不过思路感觉是对的,先对订单按时间排序,建一个last数组,记录每个点最后接到订单的时间,然后对每个订单处理,就能根据last[]求出因为没有接订单而减掉的优先级数量了。。然后就能知道是否加入名单,是否除名了。。。

订单处理完后,在根据last算一下到时间T减掉的优先级数,考虑一下是否被除名就行了。。

(没做对,不写代码了。。嘤嘤嘤。。)

试题 H: 修改数组

时间限制: 1.0s 内存限制: 256.0MB 本题总分:20 分
【问题描述】 给定一个长度为 N 的数组 A = [A1,A2,···AN],数组中有可能有重复出现 的整数。
现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改 A2,A3,··· ,AN。 当修改 Ai 时,小明会检查 Ai 是否在 A1 ∼ Ai−1 中出现过。如果出现过,则 小明会给 Ai 加上 1 ;如果新的 Ai 仍在之前出现过,小明会持续给 Ai 加 1 ,直 到 Ai 没有在 A1 ∼ Ai−1 中出现过。 当 AN 也经过上述修改之后,显然 A 数组中就没有重复的整数了。 现在给定初始的 A 数组,请你计算出最终的 A 数组。
【输入格式】
第一行包含一个整数 N。 第二行包含 N 个整数 A1,A2,··· ,AN 。
【输出格式】 输出 N 个整数,依次是最终的 A1,A2,··· ,AN。
【样例输入】 5     2 1 1 3 4
【样例输出】 2 1 3 4 5
【评测用例规模与约定】 对于 80% 的评测用例,1≤ N ≤10000。 对于所有评测用例,1≤ N ≤100000,1≤ Ai ≤1000000。
思路:我的做法是二分+树状数组,没加入一个数a[i],就先看(sum(a[i])-sum(a[i]-1)),==0说明a[i]没有被占用,a[i]不变,不然就二分,用树状数组sum找a[i]---1100000的第一个为0的位置,然后add上a[i]占用的数。

不过这个做法略繁琐了,有大佬直接先把1-2000000放进vector,然后用lower_bound()找位置,然后erase就可以。。。我这个不会STL的呆鸡,,写的代码有点长,幸好十分熟悉树状数组。。

试题 I: 糖果

时间限制: 1.0s 内存限制: 256.0MB 本题总分:25 分
【问题描述】
糖果店的老板一共有 M 种口味的糖果出售。为了方便描述,我们将 M 种 口味编号 1∼ M。 小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而 是 K 颗一包整包出售。 幸好糖果包装上注明了其中 K 颗糖果的口味,所以小明可以在买之前就知 道每包内的糖果口味。 给定 N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖 果。
【输入格式】
第一行包含三个整数 N、M 和 K。 接下来 N 行每行 K 这整数 T1,T2,··· ,TK,代表一包糖果的口味。
【输出格式】 一个整数表示答案。如果小明无法品尝所有口味,输出 −1。
【样例输入】 6 5 3

1 1 2

1 2 3

1 1 3

2 3 5

5 4 2

5 1 2
【样例输出】 2
【评测用例规模与约定】 对于 30% 的评测用例,1≤ N ≤20 。 对于所有评测样例,1≤ N ≤100,1≤ M ≤20,1≤ K ≤20,1≤Ti ≤ M。
思路:状压dp,应该是对的吧?感觉是对的,emmm。。记得判-1.。就ok

代码

#include
using namespace std;
typedef long long ll;
#define mod 1000000000
#define maxn 110
int a[maxn],ans,x,n,m,k,dp[2000000],vis[50],num;
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=k;j++)
        {
            scanf("%d",&x);
            a[i]|=(1<<(x-1));
            if(vis[x]==0)
            {
                vis[x]=1;
                num++;
            }
        }
    }
    if(num

试题 J: 组合数问题

时间限制: 1.0s 内存限制: 256.0MB 本题总分:25 分
【问题描述】 给 n,m,k,求有多少对 (i, j) 满足 1 ≤ i ≤ n,0 ≤ j ≤ min(i,m) 且 Cj i ≡ 0(mod k),k 是质数。其中 Cj i 是组合数,表示从 i 个不同的数中选出 j 个组成 一个集合的方案数。
【输入格式】
第一行两个数 t,k,其中 t 代表该测试点包含 t 组询问,k 的意思与上文中 相同。 接下来 t 行每行两个整数 n,m,表示一组询问。
【输出格式】
输出 t 行,每行一个整数表示对应的答案。由于答案可能很大,请输出答 案除以 109 + 7 的余数。
【样例输入】 1 2      3 3
【样例输出】 1
【样例说明】
在所有可能的情况中,只有 C1 2 = 2 是 2 的倍数。
【样例输入】

2 5

4 5

6 7
【样例输出】 0 7
【样例输入】 3 23

23333333 23333333

233333333 233333333

2333333333 2333333333
【样例输出】 851883128 959557926 680723120
【数据规模和约定】 对于所有评测用例,1≤k≤108,1≤t≤105,1≤n,m≤1018,且 k 是质数。 评测时将使用 10 个评测用例测试你的程序,每个评测用例的限制如下:
评测用例编号 t n,m k 1,2 ≤1 ≤2000 ≤100 3,4 ≤105 ≤2000 ≤100 5,6,7 ≤100 ≤1018 ≤100 8,9,10 ≤105 ≤1018 ≤108
思路:emmm,完全不会,有大佬说是规律题,似乎是能推出一个三角形有关的规律,,但是我直接放弃了。暴力了前四组,直接预处理了2000以内的所有组合数,然后求出所有对k的余数为0的个数,剩下输出的时候就直接输出了。。预处理的时候有点傻了,没有尽可能的完善,写了个不到1.2e8的预处理,,但愿能过,,

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

今年做的本来感觉还挺顺利的,然而突然发现第七题忽略了3.。。凉凉,,看看去年名单,省一一共40个,,感觉更凉了,,阿弥陀佛,去年因为女赛冲突,没能去成北京,今年让我去吧,,,,,

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

你可能感兴趣的:(蓝桥杯)