Blue Bridge Cup Day 22 (Python) (Crazy Question Day 5)

Question type:

1. Thinking questions/Miscellaneous questions: Mathematical formulas, analyzing the meaning of questions, finding patterns

2. BFS/DFS: wide search (recursive implementation), deep search (deque implementation)

3. Simple number theory: modulus, prime number (only need to judge to int (sqrt (n)) + 1), gcd, lcm, fast exponentiation (bit operation shift operation), large number decomposition (decomposition into the product of prime numbers)

4. Simple graph theory: shortest path (one-to-many (Dijstra, adjacent table, matrix implementation), many-to-many (Floyd, matrix implementation)), minimum spanning tree (and search set implementation)

5. Simple string processing: it is best to switch to list operations

6. DP: Linear DP, longest common subsequence, 0/1 knapsack problem, longest continuous string, largest increasing substring

7. Basic algorithms: binary, greedy, combination, permutation, prefix sum, difference

8. Basic data structures: queues, sets, dictionaries, strings, lists, stacks, trees

9. Commonly used modules: math, datetime, set the maximum recursion depth in sys (sys.setrecursionlimit(3000000)), collections.deque (queue), itertools.combinations (list, n) (combination), itertools.permutations (list, n) (permutation) heapq (small top heap)

Table of contents

1. Paper knife (thinking)

2. Find integers

3. "Number of Prime Factors" real problem practice (decomposition of large numbers)

 4. "Rectangular Mosaic" real practice (enumeration traversal)

5. "Elimination Game" (violent cycle)Edit

6. Reordering (differential array, greedy)

7. "The Value of Full Permutation" practice questions (mathematical theorems, thinking)

 8. "The longest non-decreasing subsequence" real practice (DP)

 9. "Optimal Clearing Scheme" real question practice (violence, line segment tree)

 10. "Splitting Numbers" real practice


1. Paper knife (thinking)

 The number of cuts is certain! Just find the rule and print the output.

2. Find integers

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)
import functools   # 自定义比较函数  -1不变,1交换


def lcm(x,y):
   return x//math.gcd(x,y)*y

x=3
step=1

b=[0,0,
   1,2,1,4,5,4,1,2,9,0,5,10,
   11,14,9,0,11,18,9,11,11,15,17,9,
   23,20,25,16,29,27,25,11,17,4,29,22,
   37,23,9,1,11,11,33,29,15,5,41,46
   ]

'''
3 5 7 8 9 11 13 15 17 19 21 23 25 27      2递增
5 8 11 14 17 20 23 26 29 32     3递增筛选    5 11 17 23  
5 9 13 17 21 25 29 33     4递增    5 17 29

'''


for i in range(2,50):  # 类似埃式筛法
   while x %i !=b[i]:   
      x+=step
   step=lcm(step,i)  # 更新步长
print(x)



 Violent traversal or finding the law, according to the previous few to find the law

3. "Number of Prime Factors" real problem practice (decomposition of large numbers)

Standard schedule:
 

n = int(input())
ans = 0
#从2开始进行质因子分解
i = 2
while i * i <= n:
    if n % i == 0:
        ans += 1
        while n % i == 0:
            n //= i
    i += 1
if n != 1:
    ans += 1
print(ans)
from random import randint
from math import gcd

def witness(a, n):
    u = n - 1
    t = 0
    while u % 2 == 0:
        u = u // 2
        t += 1
    x1 = pow(a, u, n)
    for i in range(1, t + 1):
        x2 = x1 * x1 % n
        if x2 == 1 and x1 != 1 and x1 != n - 1:
            return True
        x1 = x2
    if x1 != 1:
        return True
    return False

#miller_rabin素性测试 对数字n进行s次测试
def miller_rabin(n, s = 5):
    if n < 2:
        return False
    if n == 2:
        return True
    if n % 2 == 0:
        return False
    for i in range(s):
        a = randint(1, n - 1)
        if witness(a, n):
            return False
    return True

#返回一个因子,不一定是素因子
def pollard_rho(n):
    i, k = 1, 2
    c = randint(1, n - 1)
    x = randint(0, n - 1)
    y = x
    while True:
        i += 1
        x = (x * x + c) % n
        d = gcd(abs(x - y), n)
        if d != 1 and d != n:
            return d
        if y == x:
            return n
        if i == k:
            y = x
            k = k * 2

factor = []
#找所有的素因子
def findfac(n):
    if miller_rabin(n):
        factor.append(n)
        return
    p = n
    while p >= n:
        p = pollard_rho(p)
    findfac(p)
    findfac(n // p)

n = int(input())
findfac(n)
print(len(set(factor)))

 4. "Rectangular Mosaic" real practice (enumeration traversal)

 

 Consider the case of 4 sides, 6 sides, and 8 sides in turn, enumerate and traverse

Standard schedule:

T = int(input())
while T != 0:
    T -= 1
    a = list(map(int, input().split()))
    a = [[a[0],a[1]], [a[2],a[3]], [a[4],a[5]]]

    ans = 8
    #枚举第一个矩形下标为i,第二个矩形下标为j,第三个矩形下标为k
    for i in range(3):
        for j in range(3):
            for k in range(3):
                if i == j or i == k or j == k:
                    continue
                #枚举三个矩形的两条边
                for ii in range(2):
                    for jj in range(2):
                        for kk in range(2):
                            if a[i][ii] == a[j][jj]:
                                ans = min(ans, 6)
                                if a[i][ii] == a[k][kk]:
                                    ans = min(ans, 4)
                            if a[i][ii] == a[j][jj] + a[k][kk]:
                                ans = min(ans, 6)
                                if a[j][1 - jj] == a[k][1 - kk]:
                                    ans = min(ans, 4)

    print(ans)

5. "Elimination Game" (Cycle of Violence)

Violent cycle, scan one round, see which are marginal characters, record the subscript, delete after scanning, continue to cycle after completion, exit condition: the current character is empty or the length remains unchanged after one cycle.

Standard schedule:

s = list(input())
last_length = 0

while True:
    length = len(s)
    #如果长度等于0,终止
    if length == 0:
        print("EMPTY")
        break
    #如果长度未发生变化,终止
    if length == last_length:
        print("".join(s))
        break
    vis = [0] * length
    #根据题意找出边缘字符
    for i in range(length):
        if (i - 1) >= 0 and (i + 1) < length and s[i] == s[i - 1] and s[i] != s[i + 1]:
            vis[i] = vis[i + 1] = 1
        if (i - 1) >= 0 and (i + 1) < length and s[i] != s[i - 1] and s[i] == s[i + 1]:
            vis[i] = vis[i - 1] = 1
    #将边缘字符去除
    tmp_s = []
    for i in range(length):
        if vis[i] == 0:
            tmp_s.append(s[i])
    s = tmp_s
    last_length = length

6. Reordering (differential array, greedy)

 Preliminary idea : record the re-queried interval to see if there is an intersection, and replace the intersection interval with the maximum value

difference array

 Positive solution: read the interval, mark the number of interval visits (realized by the difference array), and then put the large value in the position with the most visits according to the greedy idea.

Standard schedule:

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)
import functools   # 自定义比较函数  -1不变,1交换


# 总体思路:查询最多的那一个放最大值,不需要序号,只需要记录最大次数
n = int(input())
a = list(map(int,input().split()))
a=[0]+a
b=[0]*(n+10)
s=[0]*(n+1)

m=int(input())
for i in range(m):
   # 差分数组实现区间加法更新
   l,r = map(int,input().split())
   b[l]+=1
   b[r+1]-=1

#对差分数组前缀和,得到每个数字的查询次数
for i in range(1,n+1):
   s[i]=s[i-1]+b[i]

# sum1为原始和,sum2为贪心后的最大值
sum1,sum2=0,0
for i in range(1,n+1):
   sum1+=a[i]*s[i]

# 贪心思想,大对大,小对小
a.sort()
s.sort()

# 计算重新排序后的
for i in range(1,n+1):
   sum2+=a[i]*s[i]
print(sum2-sum1)



7. "The Value of Full Permutation" practice questions (mathematical theorems, thinking)

Preliminary thoughts: looking for patterns? If there is no rule, just list all the permutations, cycle violence, and get as many points as you can.

 Find the law and get 20% of the data right

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)
import functools   # 自定义比较函数  -1不变,1交换


#4 0+1*3+2*3+3*3+4*3+5*3+6
#3 0+1+1+2+2+3
#2 0+1

ans=0
n = int(input())
for i in range(1,n*(n-1)//2):
   ans+=(n-1)*i%998244353
print((ans+n*(n-1)//2)%998244353)

 Positive solution: the sum of the ordinal number and the reversed ordinal number is n*(n-1)//2, the ordinal number and the reversed ordinal number are equal, n numbers have n in common! A full arrangement, that is, the sum of the order and the reverse order is n!*n*(n-1)//2, so the sum of the values ​​is the above formula divided by 2.

Standard schedule:

mod = 998244353
n = int(input())
ans = n * (n - 1) // 2 % mod
for i in range(3, n + 1):
    ans = ans * i % mod
print(ans)

 8. "The longest non-decreasing subsequence" real practice (DP)

Preliminary idea: use the DP algorithm, that is, the longest incremental subsequence template to do it, record the subscript of the longest subsequence, and use the DP array to find and traverse, from the back to the front, to see if there is an element smaller than the longest subsequence and the interval is greater than K , if yes, directly +k?

There should be a problem, there is a problem with this way of thinking! ! It is not possible to pass all the data, and the consideration is incomplete.

Positive solution: The idea is similar, through the DP longest incremental template, but it needs to be maintained with a line segment tree template, so don’t give full marks to this question, just skip it.

 9. "Optimal Clearing Scheme" real question practice (violence, line segment tree)

 Preliminary idea: first choose operation 2, then in operation 1, the violent cycle is enough

 Positive solution: The idea is the same, but my idea cannot pass through all the data. It needs to be processed with a line segment tree, and I have not learned the line segment tree.

maxn = 1000000 + 10
tree_mi = [0] * (maxn * 4)
tree_add = [0] * (maxn * 4)

n, k = list(map(int, input().split()))
a = list(map(int, input().split()))
a = [0, *a]

#线段树模板
#利用左右儿子信息更新节点o
def push_up(o):
    tree_mi[o] = min(tree_mi[o << 1], tree_mi[o << 1 | 1])

#利用节点o的lazy标记add更新左右儿子
def push_down(o):
    if tree_add[o] != 0:
        tree_add[o << 1] += tree_add[o]
        tree_mi[o << 1] += tree_add[o]
        tree_add[o << 1 | 1] += tree_add[o]
        tree_mi[o << 1 | 1] += tree_add[o]
        tree_add[o] = 0

#建树
def build(o, l, r):
    tree_add[o] = 0
    if l == r:
        tree_mi[o] = a[l]
        return
    mid = (l + r) >> 1
    build(o << 1, l, mid)
    build(o << 1 | 1, mid + 1, r)
    push_up(o)

#查询区间[L,R]的最小值
def query(o, l, r, L, R):
    if L <= l and r <= R:
        return tree_mi[o]
    push_down(o);
    mid = (l + r) >> 1
    ans = 1000000000;
    if L <= mid:
        ans = min(ans, query(o << 1, l, mid, L, R))
    if R > mid:
        ans = min(ans, query(o << 1 | 1, mid + 1, r, L, R))
    return ans

#区间更新[L,R]统一加上val
def update(o, l, r, L, R, val):
    if L <= l and r <= R:
        tree_mi[o] += val
        tree_add[o] += val
        return
    push_down(o);
    mid = (l + r) >> 1
    if L <= mid:
        update(o << 1, l, mid, L, R, val)
    if R > mid:
        update(o << 1 | 1, mid + 1, r, L, R, val)
    push_up(o);


build(1, 1, n)
ans = 0
for i in range(1, n - k + 2):
    #查询区间[i, i+k-1]的最小值
    mi = query(1, 1, n, i, i + k - 1)
    if mi == 0:                     #无法进行区间消除
        #res表示当前的a[i]
        res = query(1, 1, n, i, i)
        #把当前的a[i]置为0
        update(1, 1, n, i, i, -res)
        ans += res
    else:
        ans += mi
        #区间消除
        update(1, 1, n, i, i + k - 1, -mi)
        #res表示当前的a[i]
        res = query(1, 1, n, i, i)
        #把当前的a[i]置为0
        update(1, 1, n, i, i, -res)
        ans += res
for i in range(n - k + 2, n + 1):
    ans += query(1, 1, n, i, i)
print(ans)

 10. "Splitting Numbers" real practice

 

 Preliminary idea: large number decomposition should be able to be done, see if it can be decomposed into two prime numbers or one prime number, if yes, output yes, if not, output no

import os
import sys
import math

# 请在此输入您的代码
t= int(input())
def check(n):
  count=[]  # 记录有多少个素数
  cur=0  # 指向列表,方便记录幂次
  for i in range(2,int(math.sqrt(n))+1):
    if n%i==0:
      count.append(0)
      if len(count)>2:
        print("no")
        return
      while n%i==0:
        n=n//i
        count[cur]+=1
      cur+=1  #记录下一个质数幂次
  if n>1:
    count.append(1)
    if len(count)>2:
      print("no")
      return
  #print(count)
  if len(count)==1 and count[0]>=2:
    print('yes')
    return
  if  len(count)==2 and count[0]>=2 and count[1]>=2:
    print('yes')
    return
  print('no')

for i in range(t):
  a=int(input())
  check(a)

Positive solution: The meaning of the question seems to be mistaken. What this question asks is that as long as the power of the decomposed prime number is greater than 2, it will do. (The standard method is to use the Esperanto sieve to get all the prime numbers within 4000. To traverse each number, first judge the square and cube, and then enumerate the prime number factors within 4000. If there is a power equal to 1, directly jump out of the loop and print no)

import os
import sys
import math

# 请在此输入您的代码
t= int(input())
def check(n):
  count=0  # 记录幂次
  for i in range(2,int(math.sqrt(n))+1):
    if n%i==0:
      while n%i==0:
        n=n//i
        count+=1
      if(count<2):
        print('no')
        return
      count=0   # 复位,记数下一个质数
  if n>1:  # 剩下一个质数,幂次肯定为1,不满足
      print("no")
      return
  print('yes')

for i in range(t):
  a=int(input())
  check(a)

Standard schedule:

import os
import sys
import math

not_prime = [0]*4010
prime = []
# 预处理400以内的素数
for i in range(2,4001):
  if not_prime[i]==0:
    prime.append(i)
    for j in range(2*i,4001,i):  #埃式筛
        not_prime[j]=1

# 判断平方数
def square_number(x):
  y=int(x**0.5)
  return y*y==x or (y+1)*(y+1)==x   #防止精度出问题


# 判断立方数
def cubic_number(x):
  y=int(x**(1/3))
  return y**3==x or (y+1)**3 ==x
t = int(input())
for i in range(t):
  a=int(input())
  # 判断平方和立方
  if square_number(a) or cubic_number(a):
    print('yes')
    continue
  # 枚举4000以内因子
  falg=True
  for i in prime:
    if a%i==0:
      mi=0
      while a%i==0:
        a=a//i
        mi+=1
      if mi==1:
        falg=False
        break
  if falg:
    print('yes')
  else:
    print('no')
      
      

Guess you like

Origin blog.csdn.net/weixin_52261094/article/details/129931434