Blue Bridge Cup Day 15 (Python Edition) (Number Theory)

Find the longest common subsequence template

import os
import sys

# 请在此输入您的代码
s1=list(input())
s2=list(input())
N=1000
dp=[[0]*N for i in range(N)]
for i in range(1,len(s1)):
  for j in range(1,len(s2)):
      dp[i][j]=max(dp[i][j-1],dp[i-1][j])  
        #继承原来的最大值,用max的原因是处理初始情况,即遍历到j=1时的情况的时候
      if s1[i]==s2[j]: # 发现相等的就加1
        dp[i][j]+=1
print(dp[len(s1)-1][len(s2)-1])

Chorus formation

To make the least number of columns, we must keep the most. We thought of LIS, but LIS can only deal with the longest monotone sequence, so it cannot be used directly.
We see that here is a situation where the two ends are low and the middle is high.
In this case, the most words are the highest on the left side of the tallest person plus the highest on the right side.
Here we find.
On the left side of the person in the middle, I did a LIS from left to right.
On the right side of the person, do a LIS from right to left.
So far, we seem to have found a strategy.
By enumerating the person in the middle, and then looking at the sum of the LIS on his left and the LIS on his right, this problem can be solved.
The longest increasing subsequence, use the one-dimensional array dp[ ], i traverse [2 - n-1], traverse s[j] smaller than i, and update the current dp[ ] to the smaller s[j]+1
if __name__ == "__main__":

    # 输入并赋初值
    n = int(input().strip())

    t = list(map(int, input().split()))

    dp1 = [1] * n
    dp2 = [1] * n

    # 预处理,从左往右LIS,找最长递增子序列
    for i in range(1, n): # 从第二个开始
        for j in range(i): # 找i之前比i小的
            if t[i] > t[j]:
                dp1[i] = max(dp1[i], dp1[j] + 1)

    # 预处理,从右往左LIS
    for i in range(n - 2, -1, -1):  # 从倒数第二个开始
        for j in range(n-1, i, -1): 
            if t[i] > t[j]:
                dp2[i] = max(dp2[i], dp2[j] + 1)


    maxx = 0

    for i in range(n):
        maxx = max(maxx, dp1[i] + dp2[i] - 1)
        # 自己算了两次,所以-1
        
    print(n - maxx)
    

string edit distance



def init(s,t):

    dp = [[0 for i in range(len(t) + 1)] for j in range(len(s) + 1)]
    for i in range(len(s) + 1):
        dp[i][0] = 0

    for j in range(1,len(t) + 1):
        dp[0][j] = 999999

    return dp

if __name__ == '__main__':
    s = list(input())
    t = list(input())

    dp=init(s,t)

    for i in range(len(s)):
        for j in range(len(t)):
            if s[i] == t[j]:
                dp[i + 1][j + 1] = dp[i][j]
            else:
                dp[i + 1][j + 1] = min(dp[i][j] + 1, dp[i][j + 1])
                dp[i + 1][j + 1] = min( dp[i + 1][j + 1] ,dp[j+1][i]+1)

    print(dp[-1][-1])

fast power

位运算
通过 n&1=True,则n最低位就是1
n>>,n右移动

def fast(a,n,mod):
    ans=1
    a%=mod   # 提升运算效率,Python不用担心大数月越界问题
    while(n)>0:
        if n&1 :
            ans=(a*ans)%mod
        #a=a*a   # 翻倍
        a=(a*a)%mod   # 翻倍
        n=n>>1  # 右移一位
a,b,mod = map(int,input().split())
print(fast(a,b,mod))

least common multiple common divisor

a, b common multiple:

a*b//math.gcd(a,b)

a, b common divisor

math.gcd(a,b)

greatest least common multiple

Hankson quizzes

It must be deduced from condition 2, that is, b1 is the maximum value, traverse [1, sqrt(b1)+1] to find the number that satisfies the condition, pay attention to the common multiple and the nature of the common divisor, which can be used for pruning to speed up the operation efficiency, and pay attention to the discrimination


36 int(sqrt(36))=6 1*36 2*18 3*12 4 *
9 6*6 sqrt(36)=6
27 int(sqrt(27))=5
1*27 3* 9

Answer:

prime number sieve

36 int(sqrt(36))=6
1*36 2*18 3*12 4*9 6*6 sqrt(36)=6
27 int(sqrt(27))=5
1*27 3*9
primes = []*N  # 记录素数
cnt = 0  # 记录多少个素数
bprime = [False]*N # 标记是否筛选过

def getPrimes (n):
    global cnt, primes, bprime
    bprime[0] = True
    bprime[1] = True
    for i in range(2,n+1):
        if not bprime[i]: # 找到素数
            primes[cnt] = i  # 添加记录
            cnt +=1
            for j in range(i*2,n+1,i): # 晒选以他为因子的
                bprime[j] = True

RSA解密(用到了快速幂运算)

根据关系式反推, e*d ==X(p-1)(q-1)+1,注意n=p*q,p,q为质数,那么n只有这两个因子,没有其他因子,1不是质数
# e*d ==X(p-1)(q-1)+1
#
import math
n=1001733993063167141
d=212353
C=20190324
p=891234941
q=1123984201
e=823816093931522017

# 找p,q
'''for i in range(2,int(math.sqrt(n))+1):
    if n%i==0:
        print(i,n//i)
'''
# 找e
'''for i in range(2,n+1):
    now =i*(p-1)*(q-1)+1
    if now % d==0:  # 找到了e
        print(now//d)
        break
'''
# 解密
ans =1
c=C
while e>0:
    if e&1:
        ans=(ans*c)%n  # 取模
    c=(c*c)%n  # 取模加快运算
    e=e>>1   # 记住右移动,不然死循环
print(ans)   #记住细心,看清楚记录答案的变量
    

质因子个数(即判断有多少个质数,任何一个数都能分解为质数的乘积)

知识点

过50%的代码

# 40%
# import math
# def cheak(x):
#     for i in range(2,int(math.sqrt(x))+1):
#      if x%i==0:
#        return False
#     return True
# ans=0
# n = int(input())
# for i in range(2,n+1):  #约数包括自身
#   if n%i==0 and cheak(i):  #约数同时是素数
#     ans+=1
# print(ans)


# 过80%,只记录第一个出现的约数,第一个出现的约数必定是素数
# 标准模板,质因子分解
# n = int(input())
# ans=0
# i=2
# while i*i<=n:
#     if n%i==0:
#         ans+=1
#         while n%i==0:
#             n=n//i
#     i+=1
# if n>1:
#     ans+=1
# print(ans)

阶乘约数

MAXN = 110  
cnt = [0] * MAXN   #记录对应质数幂次

for i in range(1, 101):
    x = i
    # 质因子分解
    j = 2
    while j * j <= x:
        if x % j == 0:  # 是一个质数约数
            while x % j == 0:  #类似埃式筛
                x //= j
                cnt[j] += 1
        j += 1
    if x > 1:
        cnt[x] += 1

ans = 1
for i in range(1, 101):
    if cnt[i] != 0:
        ans *= (cnt[i] + 1)  # 0 也是一种选择

print(ans)

最少砝码问题

问题是要求最少砝码个数,那么需要将砝码利用最大化,即增加一个砝码,秤重范围不重复,刚好可以拼接。

砍竹子问题

a=[]

n=int(input())
s=list(map(int,ipnut().split()))
total=0  # 所有竹子砍的次数
cnt=0  #可以少砍的
a.append(set())
    for i in range(1,n+1):
        h=s[i-1]
        a.append(set())
        while h >1:  # 高度大于1,一直砍
            total+=1  # 记录砍的总数
            if str(h) in a[i-1]: #当前高度是否在前一个过程中出现
                cnt+=1  # 出现就记录,可以少砍一刀
            a[i].add(str(h))  #记录当前自己的高度
            f(h)  #使用魔法

丢番图方程

ax+by=c 有整数解条件: gcd(a,b)能被c整除
如果有一个特解x0,y0
那么通解为
x=x0 +(b/d)*n
y=y0 - (a/d)*n

扩展欧几里得算法

同余

,当且仅当 a mod =b mod m

也可以转换为等式,即a=b+km

同余的性质

Guess you like

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