学习笔记:蓝桥杯python基础算法(2-2)(K)——构造*

十三、构造

构造题作为常见题型,要求解题者通过观察问题结构规律,寻找通用方法以应对规模变化。解题时,需从多方面思考,如关注规模增长影响、推广规律、考虑状态转移、识别模式,需要大量练习及留意特殊情况。

构造题具有两大显著特点:一是高自由度,虽构造方式多样且有简易解法,但易致考生思路迷茫;二是形式灵活多样,不存在通用解法与共性思路,对考生观察与归纳能力要求高。

针对构造题,可采用多种解题方法,包括仔细分析题目各要素、尝试特例与极端情况找解法规律、寻找模式规律并推广、逆向构造、用数学归纳法证明、灵活运用多学科知识、反复实践总结经验以及保持耐心与信心。

在应用场景方面,构造题广泛涉及数学、图论、字符串处理、组合排列、游戏策略、逻辑推理、数据结构、动态规划、贪心算法及模拟问题等领域,通过不同场景考查选手能力。

经典例题

(一)

蓝桥小蓝喜欢数学,他特别喜欢做数学题,有一天他遇到了一个有趣的数学题:

x/1​+y/1​+z/1​=N/1​

现在给定一个正整数N,小蓝想知道当x、y、z取何值时,上述等式成立。

请你帮助小蓝找到满足条件的整数x、y、z。

输入:

输入包含一个正整数N(1 ≤ N ≤ 1000)。

输出:

如果存在满足条件的整数x、y、z,则输出一个满足条件的解,以空格分隔。如果有多组解,请输出任意一组即可。

如果不存在满足条件的解,则输出"No Solution"。

样例

  • 当N = 1时,选择x = 2, y = 3, z = 6: 1/2 + 1/3 + 1/6 = 1,满足条件。

  • 当N = 2时,选择x = 4, y = 6, z = 12: 1/4 + 1/6 + 1/12 = 1/2,满足条件。

  • 当N = 3时,选择x = 7, y = 10, z = 70: 1/7 + 1/10 + 1/70 = 1/3,满足条件。

  • 当N = 4时,选择x = 5, y = 8, z = 40: 1/5 + 1/8 + 1/40 = 1/4,满足条件。


x/1​+y/1​+z/1​=N/1​​,这个题如果数学题做的多的话,我们能够很快想到:

当N=2​时,1/2=1/4+1/4​,1/4=3/12=1/12+2/12=1/12+1/6​,所以x=4​ y=6​ z=12​

当N=3​时,1/3=1/6+1/6​,1/6=3/18=1/18+2/18=1/18+1/9​,所以x=6​ y=9​ z=18​

这里的答案就跟样例不同了,因为是构造体,答案比较开放,题目的样例是随机出现,一般出题人可能会用一些比较偏的数据误导做题人。

当N=4​时,1/4=1/8+1/8​,1/8=1/12+1/24​,所以x=8​ y=12​ z=24​

显然我们可以推导得到,当N=n​时,x=2n​ y=3n​ z=6n​为原式的一组解

这个题目可以归类于数学题目,我们只需要构造出一组满足某个式子的解。


n = int(input())
x = 2 * n
y = 3 * n
z = 6 * n
print(x,y,z)

(二 )

 【题目描述】数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一部分的数列,只记得其中N个整数。现在给出这N个整数,小明想知道包含这N个整数的最短的等差数列有几项,请输出这几项。

【输入描述】输入的第一行包含一个整数N。第二行包含N个整数A₁,A₂,…,Aₙ。(注意A₁~Aₙ并不一定是按等差数列中的顺序给出)(对于所有评测用例,2≤N≤100000,0≤Ai≤10⁹。)

【输出描述】输出一个序列表示答案


所有数字间距离最小的间隔是公差吗?

等差数列的最小间隔(实际上不是公差),例如{2,5,7},最小的间隔是2,但公差不是2,是1

这其实一个GCD构造问题,可以通过计算给定数字间的所有间隔的最大公约数(GCD)来确定。把n个数据排序,计算它们的间隔,对所有间隔做GCD,结果为公差。

同时,通过最小值、最大值和公差,可以计算出等差数列的最少数量。

最少数量等于 =(最大值-最小值)/公差+1。

从最小值到最大值依次输出即可。


import math

n = int(input())
nums = sorted(map(int, input().split()))
diffs = [nums[i + 1] - nums[i] for i in range(n - 1)] # 所有相邻元素的差

# 计算最大公约数
d = diffs[0]
for num in diffs[1:]:
    d = math.gcd(d, num)

mn, mx = nums[0], nums[-1] # 等差数列的最小值和最大值
seq = [mn + i * d for i in range((mx - mn) // d + 1)]
print(' '.join(map(str, seq)))

(三) 

 题目描述: 给定一个正整数N,你需要构造一个包含N个节点的简单连通图。节点编号从1到N。同时,设任意边的两个节点的编号为a,b。a,b需要满足:(a&1)Xor(b&1)=1。每条边的权值为边所连接的两个节点的编号和,使得的最长边和最短边之间的差值小于等于3。

输入描述:

输入包含一个正整数N (2 ≤ N ≤ 1000)。

输出描述:

先输出一个M表示总共M条连边。

然后输出包含M行,每行包含两个整数,表示图中一条边的两个节点编号。


我们先剖析一下含义: (a&1)Xor(b&1)=1

a&1判断最后一个二进制位是不是1,如果为1则为1,如果为0则为0。 显然为0时为偶数,为1时为奇数。

两个数的奇偶性做亦或等于1,那么也就是说a和b不能同时为奇数或者同时为偶数。 即a和b一个为奇数另一个为偶数。

回归题目也就是说一条边两个节点的需要一个为偶数一个为奇数。

每条边的权值为边所连接的两个节点的编号和,使得的最长边和最短边之间的差值小于等于3。

这里就比较开放了,连边的方式有很多种,既然是小于等于某个数,那我们让他们最小就好了,或者说不连最小了,没有边按目前的信息是符合题意。

显然出题人早就想到了这一点,不会让我们偷懒钻空子。你需要构造一个包含N个节点的简单连通图。

我们虽然不能一个边不连,但是最少的连通图,我们知道是树,最少连N-1边,遵循着少连接少出错的原则,我们就构建一个树即可。

结论是构建一个棵只由奇偶连边的树,使得最长边和最短边的权值不超过3。

既然不让超过3,我们使得连边的权值最小即可,因为最小肯定符合题意(如果有的话),因为最小不符合题意,那么此题无解,因为求的是不超过3。最小超过了3那其他的肯定超过3。

最小的话就是,让最大值最小,让最小值最大。

假设N为偶数的话,那就1连N,3连N-2...此时所有边的值都是N+1。

如果N为奇数怎么办?那就是在添加一个N+1的节点呗。直接挂到1上即可,如果求最优解的话其实是这样一个结构。


学习笔记:蓝桥杯python基础算法(2-2)(K)——构造*_第1张图片

奇数情况下不输出划圈的连线

def print_graph_connections(n):
    print(n-1)
    if n % 2 == 0:  # 偶
        for i in range(1, n + 1, 2):
            print(i, n - i + 1)
        for i in range(1, n - 1, 2):
            print(i, n - i - 1)
    else:  # 奇
        for i in range(3, n + 1, 2):    # 跳过最大点
            print(i, n - i + 2)
        for i in range(1, n - 1, 2):
            print(i, n - i)

n = int(input("请输入节点数n: "))
print_graph_connections(n)

(四) 

给定一个正整数n(n>0)。找到任何一个满足以下条件的整数s,或者报告没有这样的数字:

在s的十进制表示中:

  • s>0

  • s由n位数字组成

  • s中没有任何数字等于0

  • s不能被它的任何一个数字整除

输入包含多个测试用例。 输入的第一行包含一个整数t(1≤t≤400),表示测试用例的数量。 接下来的t行描述了每个测试用例。 每个测试用例包含一个正整数n(1≤n≤10^5)。 保证所有测试用例中n的总和不超过10^5。


  1. 首先,我们将最后一位数字设置为3。

  2. 然后,我们将前面的位数都设置为2,这样可以确保数不会被最后一位的3整除,由于最后一位是3不是偶数所以也没办法被2整除。

  3. 接着,我们检查前面的位数,如果前面的位数的数量是3的倍数(一个简单的知识如果个位数的和能够被3整除那么这个数也能被3整除),此时那么我们可以将第一位的2替换为一个素数(比如5或7),这样就可以确保数不会被整除,同时也满足了题目的条件

t = int(input())
for _ in range(t):
    n = int(input())
    if n == 1:
        print(-1)
    else:
        s = '2' * (n - 1) + '3'
        if (n - 1) % 3 == 0:
            s = '5' + s[1:]
        print(s)

你可能感兴趣的:(Python,Lanqiao,蓝桥杯,算法,职场和发展)