/* 头部 */ #header { position: relative; height: 280px; margin: 0; background: #020031; background: -moz-linear-gradient(45deg,#020031 0,#6d3353 100%); background: -webkit-gradient(linear,left bottom,right top,color-stop(0%,#020031),color-stop(100%,#6d3353)); background: -webkit-linear-gradient(45deg,#020031 0,#6d3353 100%); background: -o-linear-gradient(45deg,#020031 0,#6d3353 100%); background: -ms-linear-gradient(45deg,#020031 0,#6d3353 100%); background: linear-gradient(45deg,#020031 0,#6d3353 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#020031', endColorstr='#6d3353', GradientType=1); -webkit-box-shadow: inset 0 3px 7px rgba(0,0,0,.2),inset 0 -3px 7px rgba(0,0,0,.2); -moz-box-shadow: inset 0 3px 7px rgba(0,0,0,.2),inset 0 -3px 7px rgba(0,0,0,.2); box-shadow: inset 0 3px 7px rgba(0,0,0,.2),inset 0 -3px 7px rgba(0,0,0,.2); }

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 的所有数字进行累加求和,即:

\[A(n)=1+2+⋯+n \]

累乘法仪式 B(n) 则是将从 1 到 n 的所有数字进行累乘求积,即:

\[B(n)=1×2×⋯×n \]

据说,当某个数字 i 满足 \(A(i)−B(i)\) 能被 100整除时,数学精灵就会被召唤出来。

现在,请你寻找在 \(1\)\(2024041331404202\) 之间有多少个数字 \(i\),能够成功召唤出强大的数学精灵。

答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

分析

根据题目已知,我们可以得到:

\[A(n)=1+2+⋯+n=\sum_{i=1}^n i=\dfrac{n(n+1)}{2} \]

\[B(n)=1×2×⋯×n=n! \]

不难看出:

  1. \(\forall n\geq 10 ,B(n)\equiv 0 \pmod{100}\)

  2. \(\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)\)(几乎是一句废话)

对于偶数,我们就考虑的多了(鸣式)。偶数应至少是三个或者以上的连续的数和。

我们可以继续,从求和公式的奇偶性下手,令:

\[f(a,k)=a+(a+1)+⋯+(a+k-1)=\sum_{i=a}^{a+k-1} i=\dfrac{k(a+a+k-1)}{2} \]

我们重点讨论后面的求和公式项的奇偶性:\(\dfrac{k(2a+k-1)}{2}\) 。不难发现,项\(k\)和项\(2a+k-1\)的奇偶性相反;当\(k\)为奇数时,\(2a+k-1\)必然为偶数,反之亦然。

\[\therefore \forall a,k \in N;f(a,k)有奇数因数 \]

烧脑的第一部分结束了,到上一步我们证明了所有有诗意的数必然有奇数因数。也就是说,任何数如果是\(2\)的幂次方,必然没有诗意:

\[\nexists a,k \in N;f(a,k)=T,T\in\{2^n,n\in N_+\} \]

下面我们证明其必要性:任何数如果不是\(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\))。

分析

完全信息博弈。所以对于任意一个初始态,先手一定有必胜或必败策略。

博弈论中,我们将初始态分为两种:必胜和必败。

  1. 定义:开局即失败的状态为先手必败态;
  2. 对于无论先手何种合法操作,后手总能找到相应的合法操作能够转移到先手必败态的状态,称为先手必败态;
  3. 非先手必败态一律为先手必胜态。

以这题为例:

由第一条,我们知道,\(\{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\),存放先手必败态。同时遍历初始状态。

\[ n \in N;\forall s\in S,(n-s)\notin T \implies n\in 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.召唤数学精灵

题目

问题描述:

答案提交:

分析

题解

posted @ 2024-09-18 23:59  是小红吖  阅读(5038)  评论(1)    收藏  举报