文章目录
- 前言
- A
- B
- C
- D
- E
- F
- G
- H
前言
仅个人回忆,不保证正确性
貌似都是典题,针对python的长代码模拟题也没有,一小时速通了,希望不要翻车。
更新:B、G翻车了。。
A
答案:103
B
应该是按长度排序,然后从按顺序遍历判断
但是刚刚想了一下,我当时是按字典序排的。。。白给5分
C
打印Q
import sys
from collections import defaultdict
from math import inf
input=lambda:sys.stdin.readline().strip()
read=lambda:map(int,input().split())
w,h,v=read()
for i in range(1,h+w+1):
for j in range(1,v+w+1):
if i<=h:
if j<=w:print('Q',end='')
else:print('Q',end='')
print()
D
lqb
的六种排列都是合法的,求最大分割数
很明显的dp,想了想贪心应该也行
import sys
from collections import defaultdict
from math import inf
input=lambda:sys.stdin.readline().strip()
read=lambda:map(int,input().split())
t='blq'
s=input()
n=len(s)
s=' '+s
def check(a,b,c):
tmp=''.join(sorted([a,b,c]))
return True if t==tmp else False
dp=[-inf]*(n+1)
dp[0]=0
for i in range(n):
dp[i+1]=max(dp[i+1],dp[i])
if i+3<=n and check(s[i+1],s[i+2],s[i+3]):dp[i+3]=max(dp[i+3],dp[i]+1)
print(dp[n])
E
给定 n n n,求两个向量的点积 A ⋅ B ≤ n A \cdot B \leq n A⋅B≤n,四个点的坐标都是正整数
-
1 ≤ n ≤ 2 20 1\leq n \leq 2^{20} 1≤n≤220
-
实际求 x 1 x 2 + y 1 y 2 ≤ n x_1x_2+y_1y_2 \leq n x1x2+y1y2≤n
-
定义 c n t i cnt_i cnti为两个数相乘小于等于 i i i的个数,这很容易用枚举第一个数 i i i,那么第二个数 j j j的范围就是 n i \frac{n}{i} in, ∑ i = 1 n n i = n lg n \sum_{i=1}^n \frac{n}{i}=n \lg n ∑i=1nin=nlgn,令 c n t [ i j ] + + cnt[ij]++ cnt[ij]++,然后再一遍前缀和累加即可
-
再用一次调和级数枚举 x 1 = i , x 2 = j x_1=i,x_2=j x1=i,x2=j,那么累加答案 a n s + = c n t [ n − i j ] ans+=cnt[n-ij] ans+=cnt[n−ij]
-
复杂度 O ( n log n ) O(n \log n) O(nlogn)
import sys
from collections import defaultdict
from math import inf
input=lambda:sys.stdin.readline().strip()
read=lambda:map(int,input().split())
n=int(input())
cnt=[0]*(n+1)
for i in range(1,n+1):
for j in range(1,n+1):
if i*j>n:break
cnt[i*j]+=1
for i in range(1,n+1):cnt[i]+=cnt[i-1]
ans=0
for i in range(1,n+1):
for j in range(1,n+1):
if i*j>n:break
ans+=cnt[n-i*j]
print(ans)
F
- 等间隔的最长上升序列
- n ≤ 5000 n \leq 5000 n≤5000
- 第一维枚举间隔 i i i,第二维枚举 j j j,那么 j % i j\%i j%i相同的位置放到同一个数组,此时他们间隔相等,对每个对应的数组直接求
import sys
from collections import defaultdict
from math import inf
input=lambda:sys.stdin.readline().strip()
read=lambda:map(int,input().split())
n=int(input())
a=list(read())
ans=0
for i in range(1,n+1):
b=[[] for _ in range(i)]
for j in range(n):
b[j%i].append(a[j])
for j in range(i):
cnt=0
for k in range(len(b[j])):
if k==0:
cnt+=1
ans=max(ans,cnt)
continue
if b[j][k]>b[j][k-1]:
cnt+=1
ans=max(ans,cnt)
continue
cnt=1
ans=max(ans,cnt)
print(ans)
G
赛时思路:
给一个排列,每次可以交换相邻的两个数,求使得他们升序的最小操作数
- 经典结论:冒泡排序的操作次数=逆序对个数
- 树状数组求逆序对即可
- 复杂度: O ( n log n ) O(n \log n) O(nlogn)
import sys
from collections import defaultdict
from math import inf
input=lambda:sys.stdin.readline().strip()
read=lambda:map(int,input().split())
class Fenwick:
def __init__(self,n):
self.c=[0]*(n+1)
self.n=n
def add(self,x,y):
while x<=self.n:
self.c[x]+=y
x+=x&-x
def query(self,x):
ans=0
while x>0:
ans+=self.c[x]
x-=x&-x
return ans
n=int(input())
a=list(read())
t=Fenwick(n+10)
ans=0
for i in range(n-1,-1,-1):
ans+=t.query(a[i]-1)
t.add(a[i],1)
print(ans)
刚刚看了流出的pdf,好像读错题了,可以交换任意位置。。。
那就是置换环的数量为
m
m
m,答案为
n
−
m
n-m
n−m
import sys
from collections import defaultdict
from math import inf
input=lambda:sys.stdin.readline().strip()
read=lambda:map(int,input().split())
n=int(input())
a=[0]+list(read())
vis=[0]*(n+1)
cnt=0
for i in range(1,n+1):
if vis[i]:
continue
x=i
cnt+=1
while not vis[x]:
vis[x]=1
x=a[x]
print(n-cnt)
H
求 ∑ i = 1 n ∑ j = i + 1 n ( a i ⊕ a j ) ( j − i ) \sum_{i=1}^n \sum_{j=i+1}^n (a_i \oplus a_j)(j-i) ∑i=1n∑j=i+1n(ai⊕aj)(j−i)
- 很容易想到拆位,定义 c n t 0 / 1 , i cnt_{0/1,i} cnt0/1,i为第 i i i位 0 / 1 0/1 0/1的个数, S u m 0 / 1 , i Sum_{0/1,i} Sum0/1,i为第 i i i位的下标和
- 计算答案贡献,假设当前数下标为 i i i,第 j j j位为 c c c,那么只有前面的数的第 j j j位为 c ⊕ 1 c \oplus 1 c⊕1才有贡献
- 那么 a n s + = ( c n t c ⊕ 1 , j ⋅ i − S u m c ⊕ 1 , j ) ⋅ 2 j ans+=(cnt_{c \oplus 1,j} \cdot i-Sum_{c \oplus 1,j})\cdot 2^j ans+=(cntc⊕1,j⋅i−Sumc⊕1,j)⋅2j
- 然后更新两个数组
- 复杂度 O ( n log n ) O(n \log n) O(nlogn)
import sys
from collections import defaultdict
from math import inf
input=lambda:sys.stdin.readline().strip()
read=lambda:map(int,input().split())
cnt=[[0]*25 for _ in range(2)]
Sum=[[0]*25 for _ in range(2)]
n=int(input())
a=[0]+list(read())
ans=0
for i in range(1,n+1):
for j in range(22):
c=a[i]>>j&1
ans+=(cnt[c^1][j]*i-Sum[c^1][j])*(1<<j)
cnt[c][j]+=1
Sum[c][j]+=i
print(ans)