小白月赛82题解

A-谜题:质数_牛客小白月赛82 (nowcoder.com)

直接输出7或直接输出n都行

B-Kevin逛超市 2 (简单版本)_牛客小白月赛82 (nowcoder.com)

因为折扣卷和立减卷都只有一张,对价格最高的两个进行优惠卷讨论即可

python code:

import sys

def solve():
    n,x,y = map(int,sys.stdin.readline().split())
    p = list(map(int, sys.stdin.readline().split()))
#     x = (100-x)/100
    if n == 1:
        ans = p[0] - y if p[0] > y else 0
        ans = min(ans, p[0]*x/100)
        print(ans)
        return
    p.sort()
    if p[-2] >= y:
        ans = 0
        for i in range(n):
            ans += p[i] if i!=n-1 else p[i]*x/100
        print(ans-y)
        return
    x = (100-x)/100
    tmp = p[-1]*x + p[-2]
    res = p[-2]*x + (y if p[-1] >= y else p[-1])
    ans = sum(p)
    print(ans-max(tmp,res))
        

for _ in range(int(sys.stdin.readline())):
    solve()

C-被遗忘的书籍_牛客小白月赛82 (nowcoder.com)

这题我一开始刚看完题闪过的想法是组合计数,后来想想有重复的情况而且不太规律应该纯计数不太行后来就往动态规划方面想了。

我们考虑动态规划:

很显然,没有包含txt的限制条件下一共有26^n种可能,那么我们只要考虑求出不包含txt的长为n的不同种的数量,再用26^n减去就好。

状态表示及转移方程

我们考虑一个序列的结尾,不包含txt的序列结尾有3种情况:1、以 t 结尾  2、以tx结尾  3、以其他小写字母结尾,我们考虑从后面添加小写字母以增加长度,即以序列长度为阶段,长度和结尾的字母构成状态。

f[i][j]表示长度为 的序列以 t 结尾(j=1),以 tx 结尾(j=2),其他情况(j=0)

状态转移:

tx后面不可接t:f(i,1)=f(i-1,0)+f(i-1,1)

tx只能由t接上x:f(i,2) = f(i-1,1)

显然可得:f(i,0)=f(i-1,0)\times 25+f(i-1,2)\times25+f(i-1,1)\times24

python code:

import sys

mod = 998244353
N = 2*10**5+1
f = [[0,0,0] for _ in range(N)]
f[1] = [25,1,0]
for i in range(2,N):
    f[i][1] = (f[i-1][0] + f[i-1][1]) % mod
    f[i][2] = f[i-1][1]
    f[i][0] = (f[i-1][0]*25 + f[i-1][2]*25 + f[i-1][1]*24) % mod

for _ in range(int(sys.stdin.readline())):
    n = int(sys.stdin.readline())
    ans = pow(26,n,mod) - sum(f[n])
    print((ans+mod)%mod)

D-Kevin逛超市 2 (困难版本)_牛客小白月赛82 (nowcoder.com)

问题推理及证明:

我们先对P进行降序排序,之后对于每一件商品,无非两种情况:

一、当P_{i} <= y时:y相当于 x = 0 的折扣卷

二、当P_{i} > y时:

综上所述:在价格降序排序后先折扣再立减卷再折扣卷,即立减卷在一段连续的区间使用,这样我们就不难想到下面这样的解法,详细见代码注释。

python code:

import sys

def solve():
    n,a,b,x,y = map(int, input().split())
    price = list(map(int, input().split()))
    price.sort(reverse=True)
    le = min(n, a+b)
    delta = [(price[i]*x/100 - max(price[i]-y, 0), i) for i in range(le)]
    delta.sort(reverse = True)  #折扣后的价钱比立减后的价钱贵多少,越大越靠前
    idx = 0
    while idx < le and idx < b and ((le - idx) > a or delta[idx][0] > 0):
        """
        idx < b:还有立减卷可以用
        并且
        (le - idx) > a:
            剩下的数量大于折扣卷的数量,因为那我们卷用的越多越好,
            我们直接贪心的选立减卷delta最大的,此时是倒序枚举,满足。
        delta[idx][0] > 0: 
            立减卷比折扣卷优惠更多,此时折扣卷用不完,意味着卷的数量大于n,
            此时立减卷优惠大我们用立减卷
        """
        _, i = delta[idx]
        price[i] = max(price[i] - y, 0)
        idx += 1
    while idx < le:
        """
        剩下的卷优惠大的是折扣卷,必定在中间一段
        """
        _, i = delta[idx]
        price[i] *= x / 100
        idx += 1
    print(sum(price))
    
    
for _ in range(int(sys.stdin.readline())):
    solve()

posted @ 2023-12-01 23:20  CH-Yu  阅读(3)  评论(0)    收藏  举报  来源