if A[i]==B[j] : max( dp[i-1][0...j-1]+1)。可预先计算mx,优化时间复杂度。(不重不漏)
else : dp[i-1][j] (不重不漏)
方法2(更直观)
dp[i][j]只考虑A的前i个数,B的前 j 个数的答案
dp[i][j]=
if A[i]==B[j] : dp[i-1][j-1]+1
max(dp[i][j-1], dp[i-1][j]) (有重不漏,因为是最大值,不影响)
1 2 3 4 5 6 7 8 9 10 11 12 13
# 方法一 for i inrange(1,N+1): mx = 0 for j inrange(1,M+1): if A[i]==B[j]: dp[i][j] = mx+1 else: dp[i][j] = dp[i-1][j] mx = max(dp[i-1][j],mx) for j inrange(0,M+1): ans = max(ans,dp[N][j])
1 2 3 4 5 6 7 8
# 方法二 dp = [[0for i inrange(1010)] for _ inrange(1010)] ans = 0 for i inrange(1,N+1): for j inrange(1,M+1): if A[i]==B[j]:dp[i][j] = dp[i-1][j-1]+1 else: dp[i][j] = max(dp[i][j-1],dp[i-1][j]) print(dp[N][M])
本题
dp[i][j]只考虑A的前i个数,以B[j]结尾的最长公共子序列
dp[i][j]=
if A[i]==B[j]
max( dp[i-1][k]+1) when 0<k=<j and B[k] < B[j]
优化:因为A[i]==B[j],所以有: when 0<k<j and B[k] < A[i]
外层循环A[i]不变,所以可提到外面
else
dp[i-1][j]
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
N = int(input().strip()) A = list(map(int,input().strip().split())) B = list(map(int,input().strip().split())) A = [0]+A;B = [0]+B dp = [[0for i inrange(3010)] for _ inrange(3010)] ans = 0 for i inrange(1,N+1): mx = 0 for j inrange(1,N+1): dp[i][j]=dp[i-1][j] if A[i]==B[j]: dp[i][j] = max(dp[i][j],mx+1) if A[i]>B[j]: mx = max(mx,dp[i-1][j]) ans = 0 for i inrange(1,N+1): ans = max(ans,dp[N][i]) print(ans)
MOD = 100000007 n,s,a,b = map(int,input().strip().split(" ")) k = s%n # f = [[0for i inrange(n+5)] for j inrange(n+5)]
f[0][0]=1 for i inrange(1,n): va = (n-i)*a vb = (n-i)*(-b) for j inrange(n): # 因为要取模,所以可以为负 f[i][j]=(f[i][j]+f[i-1][((j-va)%n+n)%n])%MOD f[i][j]=(f[i][j]+f[i-1][((j-vb)%n+n)%n])%MOD print(f[n-1][(s%n+n)%n])
能量项链
题意
思路
区间DP+破环为链
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
N = int(input()) A = list(map(int,input().strip().split())) for i inrange(N): A.append(A[i]) dp = [[0for i inrange(2*N+5)] for j inrange(2*N+5)]
for le inrange(2,N+1): for l inrange(2*N): if l + le -1 >= 2*N-1:break r = l + le -1 for k inrange(l,r): dp[l][r] = max(dp[l][r],dp[l][k]+dp[k+1][r]+A[l]*A[k+1]*A[r+1])
ans = 0 for i inrange(N): ans = max(ans,dp[i][i+N-1]) print(ans)
st = [Falsefor i inrange(50010)] primes = [0for i inrange(50010)] cnt = 0
deffun(n): global cnt for i inrange(2,n+1): if st[i]==False: primes[cnt]=i cnt+=1 j = 0 while primes[j]*i<=n: st[primes[j]*i] = True if i % primes[j]==0:break j+=1 fun(50000) whileTrue: try: l,r = map(int,input().split()) su = [False]*(r-l+1) for i inrange(cnt): p = primes[i] for j inrange(max(2*p,((l+p-1)//p)*p),r+1,p): su[j-l]=True li = [] for i inrange(r-l+1): if su[i]==Falseand i+l>1: li.append(i+l) mx,mi = -1,2000000000 mxa,mia = [],[] iflen(li)==1: print("There are no adjacent primes.") else: for i inrange(len(li)-1): if mx < li[i+1]-li[i]: mx = li[i+1]-li[i] mxa = [li[i],li[i+1]] if mi > li[i+1]-li[i]: mi = li[i+1]-li[i] mia = [li[i],li[i+1]] print("%d,%d are closest, %d,%d are most distant."%(mia[0],mia[1],mxa[0],mxa[1])) except : break
快速幂求逆元
题意
思路
当b和m互质时,b在%m下的逆元是b^m-2。
x/b = x*b^m-2 mod m
代码
1 2 3 4 5 6 7 8 9 10 11 12 13
defqmi(a,k,p): res = 1 while k: if k&1:res= (res*a)%p k = k>>1 a = (a*a)%p return res%p
n = int(input()) for i inrange(n): a,p = map(int,stdin.readline().strip().split()) if a%p==0:print("impossible") else: print(qmi(a,p-2,p))
n,m = map(int,input().strip().split()) n,m = n+1,m+1 ans = C(m*n,3)-m*C(n,3)-n*C(m,3) n,m = n-1,m-1 for i inrange(1,n+1): for j inrange(1,m+1): ans -= 2*(n-i+1)*(m-j+1)*(gcd(i,j)-1) print(int(ans))