15届蓝桥杯省赛PythonA组解题报告
全文地址:15届蓝桥杯省赛A组解题报告
A.拼正方形
题目
问题描述
小蓝正在玩拼图游戏,他有 \(7385137888721\) 个 \(2×2\)的方块和 \(10470245\) 个 \(1×1\) 的方块,他需要从中挑出一些来拼出一个正方形,比如用 \(3\) 个 \(2×2\) 和 \(4\) 个 \(1×1\) 的方块可以拼出一个 \(4×4\) 的正方形,用 \(9\) 个 \(2×2\) 的方块可以拼出一个 \(6×6\) 的正方形,请问小蓝能拼成的最大的正方形的边长为多少。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
分析
一道不怎么好玩的数学题,跟算法一点关系也没有。
知识点:按win+r,输入calc可以打开电脑上的计算器。
第一步:计算理论能拼成的最大正方形:
\(\sqrt{7385137888721*4+10470245*1}=5435123\)
第二步:计算该正方形是否可行:
由于\(5435123\)是一个奇数,所以必然四周包裹着一拳\(1*1\)的正方形(这是唯一可行的拼凑方法)。计算发现,\(1*1\)的正方形个数最大只能支持包裹边长为\(5235122\)的正方形
第三步:更换其他可能的正方形:
中间的\(2*2\)可以组成最大\(5435122\)边长的正方形。由第二步可知不存在其他方案更大,故此题答案为\(5435122\)
题解
5435122
B.召唤数学精灵
题目
问题描述
数学家们发现了两种用于召唤强大的数学精灵的仪式,这两种仪式分别被称为累加法仪式 \(A(n)\)和累乘法仪式 \(B(n)\)。
累加法仪式 A(n)是将从 1 到 n 的所有数字进行累加求和,即:
累乘法仪式 B(n) 则是将从 1 到 n 的所有数字进行累乘求积,即:
据说,当某个数字 i 满足 \(A(i)−B(i)\) 能被 100整除时,数学精灵就会被召唤出来。
现在,请你寻找在 \(1\) 到 \(2024041331404202\) 之间有多少个数字 \(i\),能够成功召唤出强大的数学精灵。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
分析
根据题目已知,我们可以得到:
不难看出:
-
\(\forall n\geq 10 ,B(n)\equiv 0 \pmod{100}\)
-
\(\dfrac{n(n+1)}{2}\equiv \dfrac{(n+200)(n+201)}{2} \pmod{100}\)
(也即$A(n)\equiv A(n+200) \pmod{100} $)
这两个式子代表什么呢?代表着存在有循环长度为\(200\)的特定的\(n\geq10\)可以满足题目中给的条件。具体的有:24,175,199,200,224,375,399,400,424,575,599,600,624,775...
可以看到在每\(200\)个数中出现了\(4\)个,故在\(2024041331404202\)中,有\(40480826628084\)个\(i\)符合题意。
注意:我们此处没有讨论\(1-10\)之间的符合条件的数。实际上其中仍然有两个\(A(1)=B(1),A(3)=B(3)\),故最后答案应该为\(40480826628086\)
QED
题解
40480826628086
C.数字诗意
题目
问题描述:在诗人的眼中,数字是生活的韵律,也是诗意的表达。
小蓝,当代顶级诗人与数学家,被赋予了"数学诗人"的美誉。他擅长将冰冷的数字与抽象的诗意相融合,并用优雅的文字将数学之美展现于纸上。
某日,小蓝静坐书桌前,目光所及,展现着 \(n\) 个数字,它们依次为 \(a_1,a_2,…,a_n\),熠熠生辉。小蓝悟到,如果一个数能够以若干个(至少两个)连续的正整数相加表示,那么它就蕴含诗意。例如,数字 \(6\) 就蕴含诗意,因为它可以表示为 \(1+2+3\)。而 \(8\) 则缺乏诗意,因为它无法用连续的正整数相加表示。
小蓝希望他面前的所有数字都蕴含诗意,为此,他决定从这 \(n\)个数字中删除一部分。请问,小蓝需要删除多少个数字,才能使剩下的数字全部蕴含诗意?
分析
不难发现,对于奇数可以写作两个连续的数的和:
\(\forall n=2k+1,k\in N,n=k+(k+1)\)(几乎是一句废话)
对于偶数,我们就考虑的多了(鸣式)。偶数应至少是三个或者以上的连续的数和。
我们可以继续,从求和公式的奇偶性下手,令:
我们重点讨论后面的求和公式项的奇偶性:\(\dfrac{k(2a+k-1)}{2}\) 。不难发现,项\(k\)和项\(2a+k-1\)的奇偶性相反;当\(k\)为奇数时,\(2a+k-1\)必然为偶数,反之亦然。
烧脑的第一部分结束了,到上一步我们证明了所有有诗意的数必然有奇数因数。也就是说,任何数如果是\(2\)的幂次方,必然没有诗意:
下面我们证明其必要性:任何数如果不是\(2\)的幂次方,必然有诗意:
随机取一个非\(2\)的幂次方的偶数\(n\),将其写作一个奇数\(o\)和一个偶数\(e\)的乘积:\(n=o*e\)
-
当\(o>e\)时,令\(k=e\),则\(a=\dfrac{o+1-e}{2}\),不难看出\(a\in N_+\);
-
同理,当\(o<e\)时,令\(k=o\),则\(a=\dfrac{e+1-o}{2}\),不难看出\(a\in N_+\).
由上,对每个\(n\),我们总能找到符合要求的\(f(a,k)\),充分性可以证明。
所以,题目中需要的诗意数字 ,只需要判断其是否为\(2\)的幂次方即可。
#include<bits/stdc++.h>
using namespace std;
long long n,m,ans;
bool chk(long long k){
int s=0;
while(k){
s+=k&1;
k>>=1;
}
if(s==1)return true;
return false;
}
int main(){
cin>>n;
for(register int i =1;i<=n;i++){
cin>>m;
if(chk(m))ans++;
}
cout<<ans;
}
题解
D.回文数组
题目
问题描述:
小蓝在无聊时随机生成了一个长度为 \(n\) 的整数数组,数组中的第 $i 个数为 \(a_i\),他觉得随机生成的数组不太美观,想把它变成回文数组,也是就对于任意 \(i∈[1,n]\) 满足 \(a_i=a_{n−i+1}\)。小蓝一次操作可以指定相邻的两个数,将它们一起加 \(1\) 或减 \(1\);也可以只指定一个数加 \(1\) 或减 \(1\),请问他最少需要操作多少次能把这个数组变成回文数组?
分析
题解
E.召唤数学精灵
题目
问题描述:
答案提交:
分析
题解
F.砍柴
题目
问题描述:
小蓝和小乔正在森林里砍柴,它们有 \(T\) 根长度分别为 \(n_1,n_2,⋯,n_T\) 的木头。对于每个初始长度为 \(n\) 的木头,小蓝和小乔准备进行交替砍柴,小蓝先出手。
每次砍柴时,若当前木头长度为 \(x\),需要砍下一截长度为 \(p\) 的木头,然后换另一个人继续砍,其中 \(2≤p≤x 且 p 必须为质数\)。当轮到某一方时 \(x=1\) 或 \(x=0\),它就没法继续砍柴,它就输了。它们会使用最优策略进行砍柴。请对每根木头判断是小蓝赢还是小乔赢,如果小蓝赢请输出 \(1\)(数字 \(1\)),如果小乔赢请输出 \(0\)(数字 \(0\))。
分析
完全信息博弈。所以对于任意一个初始态,先手一定有必胜或必败策略。
博弈论中,我们将初始态分为两种:必胜和必败。
- 定义:开局即失败的状态为先手必败态;
- 对于无论先手何种合法操作,后手总能找到相应的合法操作能够转移到先手必败态的状态,称为先手必败态;
- 非先手必败态一律为先手必胜态。
以这题为例:
由第一条,我们知道,\(\{0,1\}\)是先手必败态集合(定义);
对于\(\{2,3,4,5,6,7,8\}\),总能找到一步合法操作,转移到后手上时成为先手必败态\(\{0,1\}\);(\(2-2,3-3,4-3,5-5,6-5,7-7,8-7\));
对于\(\{9,10\}\),所有的合法操作转移到后手上时都是先手必胜态,所以\(\{0,1,9,10\}\)是先手必败态.
多重复几遍这样的操作,你会发现这个过程很像动态规划。对于一个初始状态,如果任意合法操作都不能将其导向先手必败态,那么这个初始状态就是一个先手必败态。
我们可以建一个集合\(S\),先处理出所有合法操作(也即质数集),再新建一个集合\(T\),存放先手必败态。同时遍历初始状态。
你当然可以代码实现这种事情,但是时间复杂度是\(O(n^2T)\),保险起见我们可以在考场上打表解题。
顺便说一句,赛场上我也是用的这种方法,试出来比赛系统的代码上线是\(100kB\)
题解
打表程序:
#include<bits/stdc++.h>
using namespace std;
int p[100009]= {1,2,3},p0=2;
int los[100009]={0,0,1},l0=2;
void isprime() {
for(register int k=5; k<=100000; k++) {
bool chk=1;
for(register int i=1; i<=p0; i++) {
if(k%p[i]==0) {
chk=0;
break;
}
}
if(chk)p0++,p[p0]=k;
}
}
int main() {
freopen("Eans.txt","w",stdout);
isprime();
for(register int i=2; i<=100000; i++) {
bool chk=1;
for(register int j=1;j<=p0;j++){
if(i<p[j])break;
if(binary_search(&los[1],&los[l0+1],i-p[j])){
chk=0;
break;
}
}
if(chk)l0++,los[l0]=i;
}
cout<<l0<<endl;
for(register int i=1;i<=l0;i++){
printf("%d,",los[i]);
}
fclose(stdout);
return 0;
}
提交程序:
#include<bits/stdc++.h>
using namespace std;
int ans[]={0,1,9,10,25,34,35,49,55,85,91,100,115,121,125,133,145,155,169,175,187,195,205,217,235,247,253,259,265,289,后略};
int main(){
int T,q;
cin>>T;
while(T--){
cin>>q;
if(binary_search(ans,ans+15066,q))cout<<0<<endl;
else cout<<1<<endl;
}
}
C.召唤数学精灵
题目
问题描述:
答案提交:
分析
题解
C.召唤数学精灵
题目
问题描述:
答案提交:
分析
题解
C.召唤数学精灵
题目
问题描述:
答案提交:
分析
题解
C.召唤数学精灵
题目
问题描述:
答案提交: