AcWing 蓝桥杯C++ AB组辅导课学习记录(Python,备战蓝桥杯)Day1 - Day30

1. 在学习这个课程的同时,每三天复习一下算法基础课(重做一下习题),将基础课的知识用思维导图归纳下。

2. 2022.2.12 - 2022.2.24:花两周时间把Python的两套蓝桥杯真题写了

3. 蓝桥杯学完和基础课复习完就刷acwing上的蓝桥杯题(用IDLE编译器coding),这样子一共做过的题目数量应该在300道左右。

Day 1 (2021.12.25)

递归的执行顺序:

2^20 = 10^6

2^63 = 10^8

# acwing 92. 递归实现指数型枚举

# 代码 1,使用append和pop操作

def dfs(u):
    if u==n+1:
        print(' '.join(map(str,a)))
        return
    a.append(u)
    dfs(u+1)
    a.pop()
    dfs(u+1)

if __name__ == '__main__':
    a = []
    n = int(input())
    dfs(1)

# 代码 2,使用修改操作

N = 16

def dfs(u):
    if u==n+1:
        for i in range(1,N):
            if a[i]==1: print(i, end=' ')
        print()
        return

    a[u]=1
    dfs(u+1)
    a[u]=0
    dfs(u+1)

if __name__ == '__main__':
    a = [0]*N
    n = int(input())
    dfs(1)

 

实验后发现对列表赋值这个操作是非常耗时间的

 

Day 2 (2021.12.26)

 

# acwing 94. 递归实现排列型枚举
N = 10

def dfs(u):
    if u>n:
        print(' '.join(map(str, a)))
        return
    for i in range(1,n+1):
        if not st[i]:
            st[i] = True
            a.append(i)
            dfs(u+1)
            a.pop()
            st[i] = False
    return


if __name__ == '__main__':
    st, a = [False]*N, []
    n = int(input())
    dfs(1)

 

 

# acwing 93. 递归实现组合型枚举
N = 30

def dfs(u):
    if u>m:
        print(' '.join(map(str, a)))
        return 0

    for i in range(1,n+1):
        if not st[i]:
            if len(a) and a[-1]>i:
                continue
            st[i] = True
            a.append(i)
            dfs(u+1)
            st[i] = False
            a.pop()
    return 0

if __name__ == '__main__':
    n, m = map(int, input().split())
    a, st = [], [False]*N
    dfs(1)


# yxc 思路
# -----------------------------------------------------------

N = 30

def dfs(u, start):
    # 剪枝
    if len(a)+n-start+1 < m: return
    if u>m:
        print(' '.join(map(str, a)))
        return

    for i in range(start, n+1):
        a.append(i)
        dfs(u+1,i+1)
        a.pop()

if __name__ == '__main__':
    a = []
    n, m = map(int, input().split())
    dfs(1,1)

 

 

# acwing. 1209. 带分数

def count(u, inv_u):
    global res
    u, idx = str(u), 1

    while True:
        numerator, denominator, idx = str(idx*inv_u), str(idx), idx+1

        if len(numerator) + len(denominator) > 9-len(u): break
        s = set(list(numerator+denominator+u))
        if '0' in s: continue
        for i in range(1,10):
            if str(i) not in s: break
            if i==9: res+=1


if __name__ == '__main__':
    n, res = int(input()), 0
    for i in range(1,n):
        count(i,n-i)
    print(res)
# Acwing 1209. 带分数

# yxc 的思路一,直接全排列的方法超时

N = 10

def count(l,r):
    res = 0
    for i in range(l,r+1):
        res = res*10+a[i]
    return res

def check():
    global res

    for i in range(1,8):
        if count(1, i) > n: break
        for j in range(i+1,9):
            if (n - count(1,i)) * count(i+1,j) == count(j+1,9):
                res += 1

def dfs(u):
    if u>9:
        check()
        return

    for i in range(1,10):
        if not st[i]:
            a.append(i)
            st[i] = True
            dfs(u+1)
            st[i] = False
            a.pop()
    return

if __name__ == '__main__':
    n = int(input())
    a, st = [0], [False]*N
    res = 0
    dfs(1)
    print(res)
# yxc 的思路 2

N = 10

def check(tmp_a, tmp_c):
    global res

    tmp_b = (n - tmp_a) * tmp_c
    tmp_str = list(str(tmp_b) + str(tmp_c) + str(tmp_a))
    if len(tmp_str) != 9: return False
    for i in range(1, 10):
        if str(i) not in tmp_str: return False
    return True

def dfs_c(u, tmp_a, tmp_c):
    global res

    if u>9: return
    if check(tmp_a, tmp_c): res += 1

    for i in range(1,10):
        if not st[i]:
            st[i] = True
            dfs_c(u+1, tmp_a, tmp_c*10+i)
            st[i] = False

def dfs_a(u, tmp_a):
    if tmp_a>=n: return
    if tmp_a: dfs_c(u, tmp_a, 0)

    for i in range(1,10):
        if not st[i]:
            st[i] = True
            dfs_a(u+1, tmp_a*10+i)
            st[i] = False
    return

if __name__ == '__main__':
    n = int(input())
    st = [False]*N
    res = 0
    dfs_a(0, 0)
    print(res)

Day 3 (2021.12.27)

# acwing 717. 简单斐波那契

if __name__ == '__main__':
    a, b = 0, 1
    n = int(input())
    for _ in range(n):
        print(a, end=' ')
        b, a = a+b, b

Day 4 (2021.12.28)

 递归是把子问题分解成同类子问题,递推先把子问题做完,再用子问题把原问题解出来

# acwing 95. 费解的开关

import copy

directions = [(1,0),(0,1),(0,-1),(-1,0),(0,0)]

def turn(x,y,cur_w):
    for direction in directions:
        a, b = x + direction[0], y + direction[1]
        if a>=0 and a<5 and b>=0 and b<5: cur_w[a][b] ^= 1

def light():
    res = 0x3f3f3f3f
    
    for op in range(1<<5):
        copy_w, step = copy.deepcopy(w), 0
        for i in range(5):
            if (op>>i)&1:
                step += 1
                turn(0,i,copy_w)

        for i in range(4):
            for j in range(5):
                if copy_w[i][j]==0:
                    step += 1
                    turn(i+1,j,copy_w)

        flag = True
        for i in range(5):
            if copy_w[4][i]==0:
                flag = False
                break

        if flag: res = min(res, step)

    return res if res<=6 else -1

if __name__ == '__main__':
    n = int(input())
    for i in range(n):
        w = []
        for j in range(5):
            w.append([int(x) for x in list(input())])
        if i!=n-1: input()
        print(light())

Day 5 (2021.12.30)

# acwing 116. 飞行员兄弟

import copy

def turn(x,y,cur_w):
    for i in range(4):
        if cur_w[x][i] == '+': cur_w[x][i] = '-'
        else: cur_w[x][i] = '+'
        if cur_w[i][y] == '+': cur_w[i][y] = '-'
        else: cur_w[i][y] = '+'

    if cur_w[x][y] == '+': cur_w[x][y] = '-'
    else: cur_w[x][y] = '+'

def findWay():
    ways, res = [], 0x3f3f3f3f
    for op in range(1,1<<16):
        copy_w, step, temp_ways = copy.deepcopy(w), 0, []

        for i in range(16):
            if (op>>i)&1:
                step += 1
                temp_ways.append((i//4+1,i%4+1))
                turn(i//4,i%4,copy_w)

        flag = True
        for i in range(16):
            if copy_w[i//4][i%4] == '+':
                flag = False
                break

        if flag and res>step:
            res, ways = step, temp_ways

    return res, ways


if __name__ == '__main__':
    w = []
    for _ in range(4):
        w.append(list(input()))
    times, ans = findWay()
    print(times)
    for item in ans:
        print(item[0], item[1])

Day 6 (2022.1.2)

# 自己的思路是,一定会有偶数个不同
# 则要使这偶数个不同变成相同,需要两两一组,如:0,2  6,13  14,15
# 操作步数则是2-0 + 13-6 + 15-14

# acwing 1208. 翻硬币

if __name__ == '__main__':
    a, b = list(input()), list(input())
    st = [1 if a[i]==b[i] else 0 for i in range(len(a))]
    res, z_list = 0, []
    for i in range(len(a)):
        if not st[i]:
            z_list.append(i)

    for i in range(0,len(z_list),2):
        res += z_list[i+1] - z_list[i]
    print(res)

# acwing 1208. 翻硬币

if __name__ == '__main__':
    a, b = list(input()), list(input())
    step = 0
    for i in range(len(a)-1):
        if a[i]!=b[i]:
            step += 1
            if a[i]=='*': a[i]='o'
            else: a[i]='*'
            if a[i+1] == '*': a[i+1] = 'o'
            else: a[i+1] = '*'
    print(step)

Day 7 (2022.1.3)

今天复习了八数码这道题,然后写了下面这个代码,发现过不了,最后研究发现应该是deepcopy很耗时间。

from collections import deque
from copy import deepcopy
from collections import defaultdict

directions = [(1,0),(0,1),(-1,0),(0,-1)]

def bfs():
    tried, q = defaultdict(int), deque()
    q.append((w,0))

    while q:
        now_state, step = q.popleft()
        x, y = now_state.index('x')//3, now_state.index('x')%3
        for direction in directions:
            now_state_copy = deepcopy(now_state)
            x_op, y_op = x+direction[0], y+direction[1]
            if x_op>=0 and x_op<3 and y_op>=0 and y_op<3:
                now_state_copy[x_op*3+y_op], now_state_copy[x*3+y] = now_state_copy[x*3+y], now_state_copy[x_op*3+y_op]

                if not tried[str(now_state_copy)]:
                    tried[str(now_state_copy)] = step+1
                    q.append((now_state_copy, step+1))
                    if now_state_copy==right:
                        print(step+1)
                        return
        print(-1)
        return

if __name__ == '__main__':
    w, right = list(input().split()), list('12345678x')
    bfs()

Day 8 (2022.1.4)

二分基础课学过,这里就复习下题。

两个点:1.左边界是找所有>=x的数 2.if 判断 l 的时候求mid要+1除以2(简称let it go)

# acwing 789. 数的范围

if __name__ == '__main__':
    n, q = map(int, input().split())
    a = [int(x) for x in input().split()]
    for _ in range(q):

        k = int(input())

        l, r = 0, len(a) - 1
        while l < r:
            mid = (l + r) // 2
            if a[mid] >= k:
                r = mid
            else:
                l = mid + 1

        if a[l]!=k:
            print('-1 -1')
            continue
        else: print(l, end=' ')

        l, r = 0, len(a) - 1
        while l < r:
            mid = (l + r + 1) // 2
            if a[mid] <= k:
                l = mid
            else:
                r = mid - 1
        print(l)

Day 9 (2022.1.5)

# acwing 790. 数的三次方根

eps = 1e-8

if __name__ == '__main__':
    n = float(input())
    l, r = -100, 100
    while True:
        mid = (l+r)/2
        if abs(abs(mid**3)-abs(n)) < eps:
            print("{:.6f}".format(mid))
            exit(0)
        elif mid**3<n: l=mid
        else: r=mid
# acwing 730. 机器人跳跃问题
# yxl 的思路是可以优化提前退出for循环,只要当前mid>1e5

# 版本 1,还是推荐版本 2哈,跟着模板走

if __name__ == '__main__':
    n = int(input())
    a = [int(x) for x in input().split()]
    l, r = min(a), max(a)

    while l<r:
        mid = (l+r)//2
        flag = True
        for i in range(n):
            if a[i]>mid:
                mid = mid - (a[i]-mid)
                if mid<0:
                    l = (l+r)//2+1
                    flag = False
                    break
            else: mid = mid + (mid-a[i])
        if flag: r = (l+r)//2
    print(l)


# 版本 2

# acwing 730. 机器人跳跃问题

def check(k):
    for i in range(n):
        k = 2*k - a[i]
        if k<0: return False
    return True

if __name__ == '__main__':
    n = int(input())
    a = [int(x) for x in input().split()]
    l, r = 0, max(a)

    while l<r:
        mid = (l+r)//2
        if check(mid): r=mid
        else: l=mid+1
    print(l)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n;
int h[N];

bool check(int e)
{
    for (int i = 1; i <= n; i ++ )
    {
        e = e * 2 - h[i];
        if (e >= 1e5) return true;
        if (e < 0) return false;
    }
    return true;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &h[i]);

    int l = 0, r = 1e5;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }

    printf("%d\n", r);

    return 0;
}

Day 10 (2022.1.6)

# acwing 1221. 四平方和
# Python 3 通过版,太多判断浪费时间。

import math

if __name__ == '__main__':
    n = int(input())
    s, root = {}, int(math.sqrt(n)+2)
    
    for c in range(root):
            for d in range(c,root):
                t = c*c + d*d
                if t not in s: s[t] = (c,d)

    for a in range(root):
        for b in range(a,root):
            t = n - a*a - b*b
            if t in s:
                print(a,b,s[t][0],s[t][1])
                exit()

# acwing 1221. 四平方和

from collections import defaultdict

if __name__ == '__main__':
    n = int(input())
    s = defaultdict(int)
    for c in range(n+1):
        if c*c<=n:
            for d in range(c,n+1):
                t = c*c + d*d
                if t<=n:
                    # 可以替换成 if t not in s 这个操作
                    # 或者s.get(t,-1)
                    if not s[t]: s[t] = (c,d)     
                else: break
        else: break

    for a in range(n+1):
        if a*a<=n:
            for b in range(a,n+1):
                t = n - a*a - b*b
                if s[t]:
                    print(a,b,s[t][0],s[t][1])
                    exit()

# acwing 1221. 四平方和


if __name__ == '__main__':
    n = int(input())
    s = []
    for c in range(n+1):
        if c*c<=n:
            for d in range(c,n+1):
                t = c*c + d*d
                if t<=n:
                    s.append((t,c,d))
                else: break
        else: break
    s.sort()
    for a in range(n+1):
        if a*a<=n:
            for b in range(a,n+1):
                t = n - a*a - b*b
                l, r = 0, len(s)-1
                while l<r:
                    mid = (l+r)//2
                    if s[mid][0]>=t:r=mid
                    else:l=mid+1
                if s[l][0]==t:
                    print(a,b,s[l][1],s[l][2])
                    exit()

# acwing 1227. 分巧克力

def check(edge):
    res = 0
    for square in a:
        x, y = square
        res += (x//edge)*(y//edge)
    if res>=k: return True
    else: return False


if __name__ == '__main__':
    n, k= map(int,input().split())
    a, v_max = [], 0
    for _ in range(n):
        x, y = map(int,input().split())
        v_max = max(v_max,x,y)
        a.append((x,y))

    l, r = 1, v_max
    while l<r:
        mid = (l+r+1)//2
        if check(mid): l=mid
        else: r=mid-1
    print(l)

Day 11 (2022.1.7)

# acwing 99. 激光炸弹
# 这道题目描述一点都不准确!

N = 5002

if __name__ == '__main__':
    n, r = map(int, input().split())
    target, r = [[0]*N for _ in range(N)], min(5001,r)

    row, col = r, r
    for _ in range(n):
        x,y,w = map(int, input().split())
        target[x+1][y+1] += w
        row, col = max(row,x+1), max(col,y+1)

    res = 0
    for i in range(1,row+1):
        for j in range(1,col+1):
            target[i][j] += - target[i-1][j-1] + target[i-1][j] + target[i][j-1]
            if i>=r and j>=r: res = max(res, target[i][j] + target[i-r][j-r] - target[i][j-r] - target[i-r][j])

    print(res)

Day 12 (2022.1.8)

今天发现了一个问题,为什么同样的代码和数据,在本机上运行特别慢,差了几十几百倍的速度,就是acwing 99题,上面的代码和下面这个数据。

2 1000000000
0 0 1
1 1 1

解答:AcWing 1230. K倍区间 - AcWing

# acwing 1230. K倍区间
# cnt[0] 是指的它自己本身就是一个满足条件的解

N = 100010

if __name__ == '__main__':
    n, k = map(int, input().split())
    sum, cnt = [0]*N, [0]*N
    res = 0

    for i in range(1,n+1):
        sum[i] = int(input())
        sum[i] = (sum[i] + sum[i-1])%k
        res += cnt[sum[i]]
        cnt[sum[i]] += 1

    print(res + cnt[0])
# acwing 1205. 买不到的数目

if __name__ == '__main__':
    n, m = map(int,input().split())
    print((n-1)*(m-1)-1)

# acwing 1211. 蚂蚁感冒

if __name__ == '__main__':
    n = int(input())
    a = [int(x) for x in input().split()]

    # 分别表示左边向右走的蚂蚁数量,和右边向左走的蚂蚁数量
    ltr, rtl = 0, 0
    for i in range(1,n):
        if abs(a[i]) < abs(a[0]) and a[i]>0: ltr += 1
        elif abs(a[i]) > abs(a[0]) and a[i]<0: rtl += 1

    if (a[0]>0 and rtl==0) or (a[0]<0 and ltr==0): print(1)
    else: print(ltr+rtl+1)

# acwing 1216.饮料换购

if __name__ == '__main__':
    n = int(input())
    res = n
    while n>=3:
        res += n//3
        n = n//3 + n%3
    print(res)

Day 13 (2022.1.9)

今天复习了算法基础课 树形dp、记忆化搜索和蓝桥杯简单DP例题

Day 14 (2022.1.11)

# acwing 1212. 地宫取宝
# 集合划分就相当于是上一步的状态划分(把所有上一步转移到这一步的状态划分成不重不漏的几类)

N, MOD = 54, 1000000007

if __name__ == '__main__':
    n, m, k = map(int, input().split())
    f = [[[[0] * 14 for _ in range(13)] for _ in range(N)] for _ in range(N)]
    w = [[0] * (m + 1)]

    for i in range(1,n+1):
        w.append([0] + [int(x)+1 for x in input().split()])

    f[1][1][1][w[1][1]] = f[1][1][0][0] = 1
    for i in range(1,n+1):
        for j in range(1,m+1):
            if i==j==1: continue
            for cnt in range(k+1):
                for t in range(14):
                    f[i][j][cnt][t] = (f[i][j][cnt][t] + f[i-1][j][cnt][t]) % MOD
                    f[i][j][cnt][t] = (f[i][j][cnt][t] + f[i][j-1][cnt][t]) % MOD
                    if cnt>0 and w[i][j] == t:
                        for v in range(t):
                            f[i][j][cnt][t] = (f[i][j][cnt][t] + f[i - 1][j][cnt-1][v]) % MOD
                            f[i][j][cnt][t] = (f[i][j][cnt][t] + f[i][j - 1][cnt-1][v]) % MOD

    res = 0
    for i in range(14): res = (f[n][m][k][i] + res) % MOD
    print(res)

Day 15 (2022.1.13)

 

 

 

# acwing 1214. 波动数列

N, M = 1010, 100000007

if __name__ == '__main__':
    n,s,a,b = map(int, input().split())
    f = [[0]*N for _ in range(N)]

    f[0][0] = 1
    for i in range(1,n):
        for j in range(n):
            f[i][j] = (f[i-1][(j-(n-i)*a)%n] + f[i-1][(j+(n-i)*b)%n])%M
    print(f[n-1][s%n])

Day 16 (2022.1.16)

 

# acwing 1236. 递增三元组
# cnt_aa 小于等于1,2,3的数分别有多少
# 注意要给每个数+1

N = 100010

if __name__ == '__main__':
    n = int(input())
    A, B, C = [int(x)+1 for x in input().split()], \
              [int(x)+1 for x in input().split()], [int(x)+1 for x in input().split()]
    cnt_a, cnt_c, cnt_aa, cnt_cc = [0]*N, [0]*N, [0]*N, [0]*N

    for i in range(n): cnt_a[A[i]] += 1
    for i in range(1,N): cnt_aa[i] = cnt_aa[i-1] + cnt_a[i]
    for i in range(n): cnt_c[C[i]] += 1
    for i in range(1,N): cnt_cc[i] = cnt_cc[i-1] + cnt_c[i]

    res = 0
    for i in range(n):
        res += cnt_aa[B[i]-1] * (cnt_cc[N-1] - cnt_cc[B[i]])
    print(res)
# acwing 1236. 递增三元组

N = 100010

if __name__ == '__main__':
    n = int(input())
    a,b,c = [int(x)+1 for x in input().split()],\
            [int(x)+1 for x in input().split()], [int(x)+1 for x in input().split()]
    lb,gb,cnt_a,cnt_c,cnt_c_c,cnt_a_a = [0]*N, [0]*N,[0]*N,[0]*N,[0]*N,[0]*N

    for i in range(n): cnt_a[a[i]]+=1
    for i in range(1,N): cnt_a_a[i] = cnt_a_a[i-1] + cnt_a[i]
    for i in range(n): lb[i] = cnt_a_a[b[i]-1]

    for i in range(n): cnt_c[c[i]]+=1
    for i in range(1,N): cnt_c_c[i] += cnt_c_c[i-1] + cnt_c[i]
    for i in range(n): gb[i] = cnt_c_c[N-1] - cnt_c_c[b[i]]

    res = 0
    for i in range(n): res += lb[i]*gb[i]
    print(res)
# Python的-1回取到最后一个值去,所以也可以不+1
N, L = 100010, 100001

if __name__ == '__main__':
    n = int(input())
    a,b,c = [int(x) for x in input().split()],\
            [int(x) for x in input().split()], [int(x) for x in input().split()]
    lb,gb,cnt_a,cnt_c,cnt_c_c,cnt_a_a = [0]*N, [0]*N,[0]*N,[0]*N,[0]*N,[0]*N

    for i in range(n): cnt_a[a[i]]+=1
    for i in range(L+1): cnt_a_a[i] = cnt_a_a[i-1] + cnt_a[i]
    for i in range(n): lb[i] = cnt_a_a[b[i]-1]

    for i in range(n): cnt_c[c[i]]+=1
    for i in range(L+1): cnt_c_c[i] = cnt_c_c[i-1] + cnt_c[i]
    for i in range(n): gb[i] = cnt_c_c[L] - cnt_c_c[b[i]]

    res = 0
    for i in range(n): res += lb[i]*gb[i]
    print(res)

# acwing 1236. 递增三元组
# 二分算法得注意分情况讨论 >=<

N = 100010

def binary_search_great(arr, x):
    l, r = 0, n-1
    while l<r:
        mid = (l+r)//2
        if arr[mid]>=x: r=mid
        else: l=mid+1

    if arr[l]>=x: return l
    else: return n

def binary_search_less(arr, x):
    l, r = 0, n - 1
    while l < r:
        mid = (l + r + 1) // 2
        if arr[mid] <= x: l = mid
        else: r = mid - 1

    if arr[l]<=x: return n-1-l
    else: return n

if __name__ == '__main__':
    n = int(input())
    A, B, C = [int(x) for x in input().split()], \
              [int(x) for x in input().split()], [int(x) for x in input().split()]
    A.sort()
    C.sort()

    res = 0
    for i in range(n):
        res += binary_search_great(A, B[i]) * binary_search_less(C, B[i])
    print(res)

Day 17 (2022.1.17)

# acwing. 1245. 特别数的和

if __name__ == '__main__':
    n = int(input())
    res = 0
    for i in range(1,n+1):
        n_str = str(i)
        if n_str.find('2')!=-1 or n_str.find('0')!=-1 or n_str.find('1')!=-1 or n_str.find('9')!=-1:
            res += i
    print(res)

# acwing 1204. 错误票据

N = 100010

if __name__ == '__main__':
    n = int(input())
    a, st, repeat, interval = [], [0]*N, 0, 0
    
    for _ in range(n):
        a.extend([int(x) for x in input().split()])
    for i in range(len(a)):
        if st[a[i]]: repeat=a[i]
        else: st[a[i]] = True

    for i in range(min(a),N):
        if not st[i]:
            interval=i
            break

    print(interval,repeat)

Day 18 (2022.1.18)

# acwing 466. 回文日期
# 直接枚举每一天

Month = [0,31,28,31,30,31,30,31,31,30,31,30,31]

def isValidDate(date):
    year, month, day = date//10000, (date//100)%100, date%100
    if month==0 or month>12: return False
    if month==2:
        if (year%4==0 and year%100) or year%400:
            if day==0 or day>29: return False
        else:
            if day==0 or day>28: return False
    else:
        if day==0 or day>Month[month]: return False
    return True

def isPalindrom(date):
    if str(date)==str(date)[::-1]: return True
    return False

if __name__ == '__main__':
    start, end, res = int(input()), int(input()), 0
    for i in range(start, end+1):
        if isValidDate(i) and isPalindrom(i): res += 1
    print(res)
# acwing 466. 回文日期

Month = [0,31,28,31,30,31,30,31,31,30,31,30,31]

def is_valid(date):
    if date<start or date>end: return False
    year, month, day = date//10000, (date%10000)//100, date%100

    if month<1 or month>12: return False
    if month==2:
        if (year%4==0 and year%100) or (year%400==0):
            if day<1 or day>29: return False
        elif day<1 or day>28: return False
    elif day<1 or day>Month[month]: return False

    return True

if __name__ == '__main__':
    start, end, a, res = int(input()), int(input()), [], 0
    for i in range(1000,10000):
        tmp_str = str(i) + str(i)[::-1]
        a.append(int(tmp_str))

    for item in a:
        if is_valid(item): res+=1
    print(res)

Day 19 (2022.1.19)

# acwing 787. 归并排序

def merge_sort(st, ed):
    if st>=ed: return

    mid = (st + ed)//2
    merge_sort(st,mid)
    merge_sort(mid+1,ed)

    tmp_list, tmp_1, tmp_2 = [], st, mid+1
    while tmp_1<=mid and tmp_2<=ed:
        if a[tmp_1]<a[tmp_2]:
            tmp_list.append(a[tmp_1])
            tmp_1 += 1
        else:
            tmp_list.append(a[tmp_2])
            tmp_2 += 1
    tmp_list.extend(a[tmp_1:mid+1])
    tmp_list.extend(a[tmp_2:ed+1])
    a[st:ed+1] = tmp_list[:]

if __name__ == '__main__':
    n = int(input())
    a = [int(x) for x in input().split()]
    merge_sort(0,n-1)
    print(" ".join(map(str,a)))

Day 20 (2022.1.20)

# acwing 1219. 移动距离
import math
if __name__ == '__main__':
    w, m, n = map(int,input().split())
    m_row, n_row = math.ceil(m/w), math.ceil(n/w)

    if math.ceil(m/w)%2: 
        if m%w: m_col = m%w
        else: m_col = w
    else: 
        if m%w: m_col = w + 1 - m%w
        else: m_col = 1
        
    if math.ceil(n/w)%2: 
        if n%w: n_col = n%w
        else: n_col = w
    else: 
        if n%w: n_col = w + 1 - n%w
        else: n_col = 1

    res = abs(n_col-m_col)+abs(n_row-m_row)
    print(res)

 

# 将下标变成从0开始(0行,0列),则答案比上面的代码逻辑要简单的多
# 所有行号都是直接向下取整,列号都是取余。如果从1开始则要特判
# 这道题涉及到了一个知识点,就是二维变一维(
# 或者一维变二维的时候,一维下标最好从0开始)

# acwing 1219. 移动距离

if __name__ == '__main__':
    w, m, n = map(int,input().split())
    m, n = m-1, n-1
    row_m, row_n, col_m, col_n = m//w, n//w, m%w, n%w
    if row_m % 2: col_m = w - 1 - col_m
    if row_n % 2: col_n = w - 1 - col_n
    print(abs(row_m-row_n) + abs(col_m-col_n))
# acwing 1229. 日期问题
# YYMMDD, MMDDYY, DDMMYY
# 注意点:去除重复日期
MONTH = [0,31,28,31,30,31,30,31,31,30,31,30,31]

def isValidMonthAndDay(YY,MM,DD):
    if YY>=60: YY = 1900+YY
    else: YY = 2000+YY

    if MM==0 or MM>12: return False
    if MM==2:
        if (YY%4==0 and YY%100) or YY%400==0:
            if DD==0 or DD>29: return False
        elif DD==0 or DD>28: return False
    elif DD==0 or DD>MONTH[MM]: return False
    return True


if __name__ == '__main__':
    A,B,C = list(map(int,input().split('/')))
    res = set()
    if isValidMonthAndDay(A,B,C):
        if A>=60: res.add(19000000+A*10000+B*100+C)
        else: res.add(20000000+A*10000+B*100+C)
    if isValidMonthAndDay(C,A,B):
        if C>=60: res.add(19000000+C*10000+A*100+B)
        else: res.add(20000000+C*10000+A*100+B)
    if isValidMonthAndDay(C,B,A):
        if C>=60: res.add(19000000+C*10000+B*100+A)
        else: res.add(20000000+C*10000+B*100+A)

    res = list(res)
    res.sort()
    for date in res:
        date = str(date)
        print(date[:4]+'-'+date[4:6]+'-'+date[6:])


Day 21 (2022.1.21)

# acwing 1231. 航班时间
# 这道题首先这个思维就没有想到,时差一加一减就没有了
# 然后转换成秒进行计算会大大降低复杂度也没想到
# 最后格式化输出补0也没有想到简单的方法。。。
# 同时,统一输入格式可以降低复杂度

def get_time(date):
    start, end, days = date.split()
    seconds1 = int(start[:2])*3600 + int(start[3:5])*60 + int(start[6:8])
    seconds2 = int(end[:2])*3600 + int(end[3:5])*60 + int(end[6:8]) + int(days[2])*24*3600
    return seconds2-seconds1

if __name__ == '__main__':
    n = int(input())
    for _ in range(n):
        flight1, flight2 = input(), input()
        if flight1[-1] != ')': flight1 += ' (+0)'
        if flight2[-1] != ')': flight2 += ' (+0)'
        ans = (get_time(flight1) + get_time(flight2))//2
        print('{:0>2d}:{:0>2d}:{:0>2d}'.format(ans//3600,ans%3600//60,ans%60))

Day 22 (2022.1.22)

# acwing 1241. 外卖店优先级
# 直接用st[i]=True来表示是否在队列,可以减少判断是否在,然后pop的操作。

if __name__ == '__main__':
    n, m, T = map(int, input().split())
    score, last, st, orders = [0]*(n+1), [0]*(n+1), [0]*(n+1), []
    for _ in range(m): orders.append([int(x) for x in input().split()])
    orders.sort()

    for i in range(m):
        t, id = orders[i][0], orders[i][1]

        if last[id]!=t:
            score[id] -= t-last[id]-1
            if score[id]<0: score[id]=0
            if score[id]<=3: st[id]=0

        score[id] += 2
        if score[id]>5: st[id]=1
        last[id]=t

    for i in range(1,n+1):
        if last[i]<T:
            score[i] -= T-last[i]
            if score[i]<=3: st[i]=0

    res = 0
    for i in range(1,n+1): res+=st[i]
    print(res)
# acwing 1241. 外卖店优先级
# 自己写的纯暴力做法,超时了

if __name__ == '__main__':
    n, m, t = map(int, input().split())
    qprior, allscore, things = [], [0]*(n+1), []
    for _ in range(m):
        things.append([int(x) for x in input().split()])

    things.sort()
    time = 1
    q_thistime = set()

    for items in things:
        if items[0]>t: break

        if items[0]>time:
            for _ in range(items[0]-time):
                for i in range(1,n+1):
                    if i not in q_thistime:
                        allscore[i] -= 1
                        if allscore[i]<0: allscore[i]=0
                        if i in qprior and allscore[i]<=3:
                            qprior.pop(qprior.index(i))
                q_thistime.clear()
            time = items[0]

        allscore[items[1]] += 2
        q_thistime.add(items[1])
        if allscore[items[1]]>5 and items[1] not in qprior: qprior.append(items[1])

    for i in range(1, n + 1):
        if i not in q_thistime:
            allscore[i] -= 1
            if allscore[i] < 0: allscore[i] = 0
            if i in qprior and allscore[i] <= 3:
                qprior.pop(qprior.index(i))

    print(len(qprior))

Day 23 (2022.1.23)

树状数组和线段树

 如果不需要修改的话直接用前缀和最好,但需要修改的话就要用树状数组了。

 末尾有几个0,就在第几层

 求和:

 更新:

# acwing 1264. 动态求连续区间和
# 注意:区间下标要从1开始

def lowbit(x):
    return x&-x

def add(x, v):
    while x<=n:
        tr[x] += v
        x += lowbit(x)

def query(x):
    res = 0
    while x>=1:
        res += tr[x]
        x -= lowbit(x)
    return res

if __name__ == '__main__':
    n, m = map(int, input().split())
    a, tr= [0] + [int(x) for x in input().split()], [0]*(n+1)

    for i in range(1,n+1): add(i, a[i])
    for _ in range(m):
        k, x, y = map(int, input().split())
        if k==0: print(query(y)-query(x-1))
        else: add(x,y)
# acwing 1210. 连号区间数
# 遍历一维区间的子区间的两种方式
# 1. 按左端点遍历 for i in range(n): for j in range(i,n): [i:j]
# 2. 按右端点遍历 for i in range(n): for j in range(i,-1,-1): [j:i]


if __name__ == '__main__':
    n = int(input())
    a, res = [int(x) for x in input().split()], 0

    for i in range(n):
        a_max, a_min = a[i], a[i]
        for j in range(i, n):
            a_max, a_min = max(a_max, a[j]), min(a_min, a[j])
            if j-i==a_max-a_min: res += 1
    print(res)

if __name__ == '__main__':
    n = int(input())
    a, res = [int(x) for x in input().split()], 0

    for i in range(n):
        a_max, a_min = a[i], a[i]
        for j in range(i,-1,-1):
            a_max, a_min = max(a_max, a[j]), min(a_min, a[j])
            if i-j==a_max-a_min: res += 1
    print(res)

Day 24 (2022.1.24)

# acwing 1265. 数星星

N = 32010

def lowbit(x):
    return x&-x

def add(x, v):
    while x<=N:
        tr[x] += v
        x += lowbit(x)

def query(x):
    res = 0
    while x>=1:
        res += tr[x]
        x -= lowbit(x)
    return res

if __name__ == '__main__':
    n = int(input())
    tr, level = [0]*N, [0]*N

    for i in range(1,n+1):
        x, y = map(int, input().split())
        x += 1
        level[query(x)] += 1
        add(x, 1)

    for i in range(n): print(level[i])

 

# acwing 1264. 动态求连续区间和

N = 100010

# 利用两个儿子来计算当前节点信息
def pushup(u):
    tr[u][2] = tr[u*2][2] + tr[u*2+1][2]

def build(u, l, r):
    # 当前已经是叶子节点,则直接存储相关信息
    if l==r: tr[u] = [l, r, w[r]]
    # 否则需要继续划分为两个区间
    else:
        # 给左右边界赋初值
        tr[u][0], tr[u][1] = l, r
        mid = (l + r)//2
        build(u*2, l, mid)
        build(u*2+1, mid+1, r)
        # 两个儿子更新完后就记得更新下当前节点信息
        pushup(u)

def query(u, l, r):
    # 注意这个函数的第二、三参数和build的不同
    # 如果当前区间已经被完全包含了,则直接返回
    if tr[u][0]>=l and tr[u][1]<=r: return tr[u][2]
    mid = (tr[u][0] + tr[u][1]) // 2
    sum = 0
    if l<=mid: sum = query(u*2, l, r)
    if r>mid: sum += query(u*2+1, l, r)
    return sum

def modify(u, x, v):
    if tr[u][0] == tr[u][1]: tr[u][2] += v
    else:
        mid = (tr[u][0] + tr[u][1]) // 2
        if x<=mid: modify(u*2, x, v)
        else: modify(u*2+1, x, v)
        pushup(u)

if __name__ == '__main__':
    n, m = map(int, input().split())
    w, tr = [0] + [int(x) for x in input().split()], [[0]*3 for _ in range(4*N)]
    # 初始化时传入根节点下标,初始化区间1 - n
    build(1, 1, n)

    for _ in range(m):
        k, a, b = map(int, input().split())
        # 求和时传入根节点编号和查询区间端点
        if k==0: print(query(1, a, b))
        # 修改时传入根节点编号,修改参数的位置和更新数值
        else: modify(1, a, b)

Day 25 (2022.1.25)

# acwing 1270. 数列区间最大值

N = 100010

def build(u,l,r):
    if l==r: tr[u] = [l,r,w[r]]
    else:
        tr[u][0], tr[u][1] = l, r
        mid = (l+r)//2
        build(u*2,l,mid)
        build(u*2+1,mid+1,r)
        tr[u][2] = max(tr[u*2][2], tr[u*2+1][2])

def query(u,l,r):
    if tr[u][0]>=l and tr[u][1]<=r: return tr[u][2]
    else:
        mid = (tr[u][0] + tr[u][1]) // 2
        max_v = 0
        if l<=mid: max_v = query(u*2,l,r)
        if r>mid: max_v = max(max_v, query(u*2+1,l,r))
        return max_v

if __name__ == '__main__':
    n, m = map(int, input().split())
    w, tr = [0] + [int(x) for x in input().split()], [[0]*3 for _ in range(4*N)]
    build(1,1,n)

    for _ in range(m):
        a, b = map(int, input().split())
        print(query(1,a,b))

Day 26 (2022.1.27)

用冒泡排序(逆序对)的思想,想要得到一个排好序的队列,有k个逆序对则至少要交换k次。

假设每一个小朋友他前面有k1个比他高,后面有k2个比他矮,那么他至少要交换k1+k2次才能够使得队列排序正确,怎样证明他只需要k1+k2次就可以使得队列排序正确呢,我们可以知道所有小朋友共交换2k(每个小朋友的交换次数都多算了一倍)(因为每次都只交换逆序对,所以是可以取到k的),而这个k就是逆序对的数量(一个逆序对需要调换两个小朋友的位置,因此小朋友会有2k次被影响),因此,可以取到k1+k2,要交换的次数就是k1+k2。

# acwing 1215. 小朋友排队

N = 1000010

def lowbit(x):
    return x&-x

def add(x, v):
    while x<=N-1:
        tr[x] += v
        x += lowbit(x)

def query(x):
    ans = 0
    while x>=1:
        ans += tr[x]
        x -= lowbit(x)
    return ans

if __name__ == '__main__':
    n = int(input())
    arr, tr = [0] + [int(x)+1 for x in input().split()], [0]*N
    sum = [0]*(n+1)

    # 计算在他前面,但比他大的数
    for i in range(1,n+1):
        sum[i] += query(N-1) - query(arr[i])
        add(arr[i],1)

    tr = [0]*N
    # 计算在他后面,但比他小的数
    for i in range(n,0,-1):
        sum[i] += query(arr[i]-1)
        add(arr[i], 1)

    res = 0
    for i in range(1,n+1):
        res += sum[i]*(sum[i]+1)//2
    print(res)

Day 27 (2022.1.28)

最外层右上角点为4k^2,然后再求到这个点的曼哈顿距离

# acwing 1237. 螺旋折线

if __name__ == '__main__':
    x, y = map(int, input().split())
    k = max(abs(x), abs(y))

    if x>=y: print((2*k)**2 + abs(x - k) + abs(y - k))
    else: print((2*k)**2 - abs(x - k) - abs(y - k))

Day 28 (2022.1.30)

解题思路和代码实现还是有差别的,解题思路又是对思路细节的一些优化。

# acwing 1238. 日志统计

N = 100010

if __name__ == '__main__':
    n, d, k = map(int, input().split())
    logs, cnt, st = [], [0]*N, [0]*N
    for _ in range(n): logs.append([int(x) for x in input().split()])
    logs.sort()

    i, j = 0, 0
    while i<n:
        ts, id = logs[i]
        cnt[id] += 1
        while ts-logs[j][0]>=d:
            cnt[logs[j][1]] -= 1
            j += 1
        if cnt[id]>=k: st[id] = 1
        i += 1

    for i in range(N):
        if st[i]: print(i)

Day 29 (2022.1.31)

今天复习799. 最长连续不重复子序。记录一堆东西是否有出现过可以用set、数组和字典,其中后两者可以记录其出现次数。

Day 30 (2022.2.3)

# acwing 1101. 献给阿尔吉侬的花束

from collections import deque

directions = [(1,0),(0,1),(0,-1),(-1,0)]

def bfs(start, end):
    q = deque([start])

    while q:
        x, y = q.popleft()
        for direction in directions:
            x_mov, y_mov = x+direction[0], y+direction[1]
            if x_mov>=1 and x_mov<=r and y_mov>=1 and y_mov<=c and dist[x_mov][y_mov]==0 and arr[x_mov][y_mov]!='#':
                dist[x_mov][y_mov] = dist[x][y]+1
                if [x_mov,y_mov] == end: return dist[x_mov][y_mov]
                q.append([x_mov,y_mov])
    return 'oop!'

if __name__ == '__main__':
    t = int(input())
    for _ in range(t):
        r, c = map(int, input().split())
        arr, dist = ['#'*(c+1)], [[0]*(c+1) for _ in range(r+1)]
        for _ in range(r):
            arr.append('#'+input())
        start, end = [], []
        for i in range(1,r+1):
            for j in range(1,c+1):
                if arr[i][j]=='S': start = [i,j]
                if arr[i][j]=='E': end = [i,j]
        res = bfs(start, end)
        print(res)

  • 15
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值