试题 F:小平方
【样例输入】
5
【样例输出】
2
思路
这道题也很简单,实际上就一个枚举就可以
简单来说,就是有手就行哈哈,第一题可能让我兴奋一下,等等就难受了
代码
''' 比较简单就是枚举即可 ''' cnt = 0 n = int(input()) for i in range(1,n): if (i*i)%n <= n/2: cnt += 1 print(cnt)
试题 G:完全平方数
【样例输入】
12
【样例输出】
3
思路
这道题的话,前面就在思考,穷举的办法行不行的通,但是后面想了想,行不通的,因为我们的最大数据有10的12次方,所以说我们需要一个更好的算法
想着想着,我突然灵机一动,我们其实可以利用一种分解质因数的思路去求解,比如说我们的样例输入中有一个12,这个12我们可以进行分解质因数,也就是12=2x2x3,我们会发现,我们只要乘上一个3,就是我们完全平方数了,也就是2x2x3x3,这样我们的数据两两配对就是平方数,所以我们的x最后就是3。
所以思路就出来了,我们需要对我们的数据进行一个分解质因数,如果我们当前质因数的个数为奇数的话,我们就需要多乘一个,所以x就乘上这个质因数,这样就可以完成配对。
对于质数来说,本身无法分解质因数,或者说,分解的质因数就是他本身,所以我们就可以直接输出本身就可以的了
代码
''' 利用一种分解质因数的方法来计算 ''' from collections import Counter h = Counter() # 计数,质因数的个数 n = int(input()) for i in range(2,int(n**0.5)+1): # 循环遍历 while n%i==0: # 进行分解质因数 n = n//i h[i] += 1 # 计算质因数个数 x = 1 for i in h: if h[i]%2 == 1: # 如果质因数的个数为奇数,就乘x x = x*i if x == 1: print(n) # 本身是一个质数,不用分解,打印自身 else: print(x) # 得到分解质因数后的值
我们也可以将代码简化一下,其实就是
n = int(input()) x = 1 for i in range(2,int(n**0.5)+1): # 循环遍历 cnt = 0 while n%i==0: # 进行分解质因数 n = n//i cnt += 1 if cnt & 1: x *= i print(n*x)
题目 H:负载均衡
【样例输入】
2 6 5 5 1 1 5 3 2 2 2 6 3 1 2 3 4 1 6 1 5 1 3 3 6 1 3 4
【样例输出】
2 -1 -1 1 -1 0
思路
这道题的话,我采用了优先队列的想法,似乎很多人是使用二重循环的,但是我觉得二重循环肯定是过不了的,因为在这一部分中数据量最大有10的9次方,最多就是10的18次方,很明显是不可能过的了的
这里就考虑了一个优先队列的思想,这里还用了二叉堆,当然也可以用queue库里面的PriorityQueue,也是优先队列,本质上这里面的优先队列也是用二叉堆实现的,所以我索性就用了二叉堆的想法。
具体呢,我觉得就是一个模拟的想法,首先我们分配一个一个电脑,如果发现电脑资源不够,就输出-1,如果发现电脑资源足够,就输出剩下的资源,不过难点就是,你怎么样记录我们的时间,因为有可能运行后面的任务的时候,前面的电脑的资源释放了,所以这时候我就用了优先队列的思想
我们可以将时间,机器,资源都放在一个元组中,然后会按时间进行排序,如果判断时间相同,就说明前面的任务释放资源了,这时候我们就把该机器的资源进行一个释放,再去对我们的任务来分配资源。这样模拟过程,就可以很容易完成我们的结果,而且速度也是很快的,我们只需要判断优先队列中的前几个是不是与当前时刻相同,一旦发现不相同的,后面的时间都是大于当前时刻的,就可以不用考虑。
不过后来我发现我考虑少了一个点,我们判断时间的时候不应该只是判断时间相等,而是一个小于等于的关系,因为可能在分配任务的时刻的中间,我们的资源就进行了释放了。
同时这里也给出一个优先队列和二叉堆的链接,Python 优先队列(priority queue)和堆(heap)
代码
import heapq heap = [] n,m = map(int,input().split()) # 计算机数和任务数 v = list(map(int,input().split())) # 计算机的资源 v = [0] + v for i in range(m): # a为时刻,b为机器,c为耗费时间,d为算力资源 a,b,c,d = map(int,input().split()) # 判断优先队列是否存有资源 while heap: x = heap[0] if x[0] <= a: # 判断释放资源的时间 是否小于等于 当前时刻 v[x[1]] += x[2] # 释放资源 heapq.heappop(heap) else: break # 判断是否有资源,如果有资源就分配,并加入优先队列 if v[b] >= d: v[b] -= d heapq.heappush(heap,(a+c,b,d)) print(v[b]) # 打印剩余算力 else: print(-1)
试题 I:国际象棋
思路
这一道题呢,我们肯定知道,如果采用dfs是一定会超时的,所以这里采用的是一种状压dp的思想
因为我们的数据中的行是n<=6的,所以我们就可以利用状态压缩DP
对于马走日这个操作而言,前前行,前行状态均会影响到本行的状态。即首先前行的马不能与前前行冲突,其次,本行的马不能与前行、前前行冲突。那么这个本行的方案就是一种可行方案。
但是我们的马的数量也有限制,所以我们还需要一个维度来进行记录,也就是我们k
理论上来讲,枚举行、列都是可以的。
但是注意状压 dp,我们一定是二进制枚举数量小的那一个维度,在此是 n,行比较小,故二进制枚举行,循环枚举列。f[i][a][b][j]表示已经放好了 i-1 列之前的马,且第 i 列状态为 b,i-1 列的状态为 a,放置马的总数量为 j 的方案数。
所以我们需要对我们的a和b进行枚举,将前行、前前行所有满足放置个数为 k 的状态进行累加,res += f[m][a][b][k]。
【样例输入】
1 2 1
【样例输出】
2
【样例输入】
4 4 3
【样例输出】
276
【样例输入】
3 20 12
【样例输出】
914051446
代码
''' 主要思路就是利用状压dp来解决 如果直接用我们的dfs应该是必会超时的 因为我们的行数和列数和马的数不是一样的 ''' # 计算二进制中1的个数,也就是计算当前列增加了多少个棋子 def lowbit(x): res = 0 while x: # print(bin(x)) res += 1 x -= x&-x # 减去最低位的1 return res n,m,k = map(int,input().split()) # f[i][a][b][t] i 代表前i列,a代表前列,b代表当前列的状态集合,t代表已经用过多少个棋子 # f[n][m][m][k] f = [[[[0]*(k+1) for _ in range(1<<n)] for _ in range(1<<n)] for _ in range(m+1)] f[0][0][0][0] = 1 # 初始化为1 MOD = int(1e9+7) for i in range(1,m+1): # 循环枚举列,二进制枚举行的情况 for a in range(1<<n): # 前一列 for b in range(1<<n): # 当前列 if (b>>2) & a or (b<<2) & a: continue for c in range(1<<n): # 前前列 if (c<<2) & a or (c>>2) & a: continue # 与上一列发生冲突 if (c<<1) & b or (c>>1) & b: continue # 与当前列发现冲突 t = lowbit(b) # 当前列放了 t 匹马 for j in range(t,k+1): # 状态转移,也就是背包计数 f[i][a][b][j] = (f[i][a][b][j] + f[i-1][c][a][j-t]) % MOD # 放了m列,当前状态为b,上一个状态为a,总共放了k 匹马的方案数 res = 0 for a in range(1<<n): for b in range(1<<n): res = (res + f[m][a][b][k]) % MOD print(res)
试题 J:完美序列
思路
这道题看我们的数据来说,还是特别大的,但是一下子让我来看的话,我就想到一种穷举的方法,对全排列的子序列进行一个枚举,如果发现,可以从小到大进行枚举,如果发现是完美子序列,就计算价值和,不过我知道,这种方法只能拿20分了,不过如果都做到这里了,拿20%的分折算就是5分了。
然后我在想,在我们计算子序列的时候,首先我们知道,对于全排列来说,我们的子序列是会有重复的,比如(3,2,1)和(2,1,3)都有子序列(2,1),这一部分如果重复枚举的话就容易造成超时
所以我觉得正确的做法是,对于合适的子序列,我们是要看在全排列中占的比例大概有多少,然后,就是互相找因数,然后判断进行计算。
不过我觉得J题现在纠结没什么意思,还是先看看其他题,准备考试了,加油
代码
# 持续更新 暂时先复习
试题的pdf在网盘里,可以自取
链接:https://pan.baidu.com/s/17qliVu31SCGtXCQVEfldZA
提取码:6666