13 条动态

仙鹤

第一次参加GPLT有感:#

本人并没有系统学习过算法知识,平时也只会用python做一点简单的题目,但最后也是很幸运地被选去参加GPLT了。

自己是个内向的人,不太擅长交友,没有一个室友陪我来自己心里就更加窘迫了,不知道有没有和我一样同感的。不过大家都比较友善,大家在一起聚餐,整体的氛围还是不错的。

再来说说比赛的事情,那个考场真的好多好多人,开赛前给我的感觉就是很严肃,很紧张。比赛开始的时候,周围就传来噼里啪啦的键盘声,让我回想起上次参加CACC自己还要看着键盘,代码敲得非常不熟练的经历。好在自己从那以后练习了十指盲打,这次没那么窘迫了。

和我想象的GPLT不一样,L1的题目很适合我这种小白做,很遗憾的是,有两个题的测试点不知道为什么过不了,这周抽个空再补补吧。看到自己L1能过80,也是想尽办法把L2-1过了,即使没有学习过算法,带着自己的思维也是能冲一把的。最后自己拿了112分,也是尽力了。学校两个队伍都是铜牌,大家都很厉害。

总结一下自己的比赛经验,也提醒一下未来要参加GPLT的同学们。当一个题的部分测试点怎么都过不了的时候,就不要过于较劲了,很浪费时间,会把后面能拿的分错过掉。还有,写代码的时候要先在比赛环境里写,再复制到IDE调试,因为我发现IDE里面的代码不能复制到比赛环境,要重新抄一遍,也很浪费时间…

大一下的课程有很多,高数,线代,大物三件套的出现,让我感觉自己已经没有之前学有余力了。近期也是熬夜得比较多,没有抽出时间按照自己的规划学习,感觉也应该多补一补觉调整一下了…

成都信息工程大学
#算法竞赛
仙鹤

不点两面#

用res记录安全牌的数量,当某张牌从0变1或者从1变0时才考虑安全牌的变化,前面的安全牌和后面的安全牌要分别讨论,注意临界问题的处理即可

m, q = map(int, input().split())
a = [0] * (m + 1)
res = 0
for _ in range(q):
    op, num = map(int, input().split())
    old = a[num]
    if op == 1:
        a[num] += 1
    else:
        a[num] -= 1
    new = a[num]
    if old == 0 and new == 1:
        if num - 3 >= 1:
            if num - 6 >= 1:
                if a[num - 6] == 0:
                    res += 1
            else:
                res += 1
        if num + 3 <= m:
            if num + 6 <= m:
                if a[num + 6] == 0:
                    res += 1
            else:
                res += 1
    elif old == 1 and new == 0:
        if num - 3 >= 1:
            if num - 6 >= 1:
                if a[num - 6] == 0:
                    res -= 1
            else:
                res -= 1
        if num + 3 <= m:
            if num + 6 <= m:
                if a[num + 6] == 0:
                    res -= 1
            else:
                res -= 1
    print(res)
牛客
#模拟
仙鹤

被打乱的异或和#

过个年太吵了,今天才回归正轨。一般思路即可通关,每个元素都考虑一次,计算其他所有元素的异或判断是否相等即可。
可以通过旋转队列实现

from collections import deque
T = int(input())
for _ in range(T):
    n = int(input())
    a = deque(map(int,input().split()))
    f = False
    i = 0
    res = 0
    while not f and i != n:
	  #计算除开第一个所有元素的异或
        x = 0
        for j in range(1,n):
            x = x ^ a[j]
		#判断是否等于假定的新元素
        if x == a[0]:
            f = True
            res = x
            break
			#找到了就停止循环
		#找不到就旋转序列,考虑下一个元素
        a.rotate(1)
        i += 1
    print(res)
牛客
#异或运算
仙鹤

相邻的糖果#

用add维护窗口的总和,每次尽量从窗口最右边的盒子减少,如果不够,就继续往左移,直到满足要求,用res记录操作的次数
虽然比较麻烦,但也是比较神秘地通关了

n,m,x = map(int,input().split())
a = list(map(int,input().split())) + [0]
add = sum(a[:m])
res = 0
for i in range(n-m+1):
    j = i + m - 1
    while add > x:
        mi = min(a[j],add-x)
        a[j] -= mi
        add -= mi
        res += mi
        j -= 1
    add -= a[i]
    add += a[i+m]
print(res)
牛客
#窗口
仙鹤

Digital Folding#

当时把自己绕进去了

T = int(input().strip())
for _ in range(T):
    L, R = input().split()
    l_int, r_int = int(L), int(R)
    n = len(R)
    
    # 构造100000...0
    t = '1' + '0' * (n - 1)
    
    if R == t:
        if L == R:
            print(1)
        else:
            print(r_int - 1)
        continue
    
    # 使L与R位数相同
    if len(L) < len(R):
        L = t
    
    k = -1
    s = ''
    for i in range(n):
        if L[i] != R[i]:
            k = i
            break
        s += R[i]

    # L和R完全相同
    if k == -1:
        # 去掉末尾的0,然后反转
        temp = L.rstrip('0')
        print(temp[::-1])
    else:
        # 检查R的k+1到末尾是否都是'9'
        ok = True
        for i in range(k + 1, n):
            if R[i] != '9':
                ok = False
                break
                
        if ok:
            print(int(R[::-1]))
        else:
            s = s + str(int(R[k]) - 1) + '9' * (n - k - 1)
            print(s[::-1])
牛客
#补题
仙鹤

躲藏#

今天看到了dp最容易理解的模样

import sys
mod = 2000120420010122
for s in sys.stdin:
    s = s.lower()
    c = cw = cwb = cwbc = 0
    for i in s:
        if i == 'c':
            c += 1
            cwbc = (cwbc + cwb) % mod
        elif i == 'w':
            cw = (cw + c) % mod
        elif i == 'b':
            cwb = (cwb + cw) % mod
    print(cwbc)
牛客
#dp
仙鹤

小红的好排列#

这涉及数学的排列组合,首先,我们知道,两数只要有一个数是三的倍数,那么他们的积也是3的倍数
分为两种情况,当n = 2时是绝对不能满足条件的
当n是大于2的偶数,是3的倍数数字的个数和是3倍数位置的个数错开是完全可以大于总数的一半的
对于第二种情况,我们使用排列组合,先考虑3倍数重叠部分,再考虑不能重叠的部分,然后考虑剩下的部分
最终,把3个部分相乘即可得到答案
因为结果要取模,要懂得运用费马小定理和模拟元的知识,自定义排列,组合,阶乘的函数

mod = 1000000007
# 阶乘
def my_fac(n):
    ans = 1
    for i in range(1, n + 1):
        ans = (ans * i) % mod
    return ans
# 组合运算
def my_comb(n, k):
    nr = my_fac(n)
    dr = (my_fac(k) * my_fac(n - k)) % mod
    inv_dr = pow(dr, mod - 2, mod)
    return (nr * inv_dr) % mod
# 排列运算
def my_perm(n, k):
    nr = my_fac(n)
    dr = my_fac(n - k)
    inv_dr = pow(dr, mod - 2, mod)
    return (nr * inv_dr) % mod

n = int(input())
# 统计3的倍数数量
b = n // 3
# 统计一半数量
c = n // 2
if n == 2:
    print(0)
else:
    # 3倍相交部分
    res = my_comb(b, 2 * b - c) % mod; res = (res * my_perm(b, 2 * b - c)) % mod
    # 3倍不相交部分
    res = (res * my_perm(n - b, c - b)) % mod
    # 剩余部分
    res = (res * my_perm(n - b, n - b)) % mod
    print(res)
牛客
#排列组合#取模运算
仙鹤

特殊的科学计数法#

直接使用语法转成科学计数法会因为数据过大而无法通过评测,所以我们取前三位研究。
系数部分根据四舍五入分为进位和不进位两种情况,指数部分只需要根据系数部分的两种情况,结合字符串长度计算即可得到。

import math
print(int(input()) * math.gcd(*map(int,input().split())))
牛客
#每日一题#科学计数法
仙鹤

小红的gcd#

首先我们要知道gcd(a,b)的意思是a和b的最大公约数,每次操作,都会将两个数变小
因为可以操作无限次,所以我们要操作到整个数组不能继续变小的情况为止
经过简单的想象,这种情况就是数组每个数都相等的情况,这个相等的数字就是全局最大公约数
所以,我们只需要算出全局公约数在乘以n即可

import math
print(int(input()) * math.gcd(*map(int,input().split())))
牛客
#每日一题#数学#gcd
仙鹤

计数#

对于每一个连续0区间,我们都可以单独算出它们的种数,通过累乘每个区间的种数即可算出结果。

那么,如何计算每个区间的种数?
这需要两个数据,一个是满足该区间条件的数字个数w,一个是该区间0的个数h。 我们用隔板法,假设有i个隔板,就有i+1个数字要填,通过排列组合,算出隔板放置组合有多少种,不同数字组合有多少种,二者相乘,即可得到单个区间种数 最后在计算的时候注意边乘边取模就好啦!

import math
mod = 1000000007
n = int(input())
#初始化结果1,便于后面累乘
res = 1 

# 初始化列表,在列表最前面加个1000,便于计算能填入的数字数量
lis = [1000] + list(map(int,input().split()))

w_h = []

#添加每个非零区间数据
l,r = 0,0
sta = True
for i,x in enumerate(lis):
    if x != 0:
        if sta:
            l = i 
        else:
            r = i
            w_h.append([lis[l]-lis[r] + 1,r-l-1])
            l = r; sta = True
    else:
        sta = False
if lis[-1] == 0:w_h.append([lis[l],n - l]) #补充遗漏

# 计算结果
for w,h in w_h:
    cnt = 0 # 计算单个区间种数
    for i in range(0,h):
        cnt = (cnt + math.comb(h-1,i) * math.comb(w,i+1)%mod)%mod
        if i + 1 == w:break
    # 累乘计算最终结果
    res = res * cnt % mod

print(res)
牛客
#每日一题#数学#排列组合