第四周算法题

01 [NOIP2001 提高组] 数的划分

题目描述

将整数 n n n 分成 k k k 份,且每份不能为空,任意两个方案不相同(不考虑顺序)。

例如: n = 7 n=7 n=7 k = 3 k=3 k=3,下面三种分法被认为是相同的。

1 , 1 , 5 1,1,5 1,1,5;
1 , 5 , 1 1,5,1 1,5,1;
5 , 1 , 1 5,1,1 5,1,1.

问有多少种不同的分法。

输入格式

n , k n,k n,k 6 < n ≤ 200 6<n \le 200 6<n200 2 ≤ k ≤ 6 2 \le k \le 6 2k6

输出格式

1 1 1 个整数,即不同的分法。

样例 #1

样例输入 #1

7 3

样例输出 #1

4

提示

四种分法为:
1 , 1 , 5 1,1,5 1,1,5;
1 , 2 , 4 1,2,4 1,2,4;
1 , 3 , 3 1,3,3 1,3,3;
2 , 2 , 3 2,2,3 2,2,3.

【题目来源】

NOIP 2001 提高组第二题

代码

def func(n, k, s=1):
    if k == 1:
        return 1
    cnt = 0
    # s 默认为 1 表示第一个切分的数值, 保证后续数值都会大于s,避免重复
    for i in range(s, n//k+1):
        cnt += func(n-i, k-1, i)
    return cnt

n, k = map(int, input().split())
print(func(n, k))

02 终于结束的起点

题目背景

终于结束的起点
终于写下句点
终于我们告别
终于我们又回到原点
……

一个个 OIer 的竞赛生涯总是从一场 NOIp 开始,大多也在一场 NOIp 中结束,好似一次次轮回在不断上演。
如果这次 NOIp 是你的起点,那么祝你的 OI 生涯如同夏花般绚烂。
如果这次 NOIp 是你的终点,那么祝你的 OI 回忆宛若繁星般璀璨。
也许这是你最后一次在洛谷上打比赛,也许不是。
不过,无论如何,祝你在一周后的比赛里,好运。

当然,这道题也和轮回有关系。

题目描述

广为人知的斐波拉契数列 f i b ( n ) \mathrm{fib}(n) fib(n) 是这么计算的

也就是 0 , 1 , 1 , 2 , 3 , 5 , 8 , 13 ⋯ 0, 1, 1, 2, 3, 5, 8, 13 \cdots 0,1,1,2,3,5,8,13,每一项都是前两项之和。

小 F 发现,如果把斐波拉契数列的每一项对任意大于 1 1 1 的正整数 M M M 取模的时候,数列都会产生循环。

当然,小 F 很快就明白了,因为 ( f i b ( n − 1 )   m o d   M \mathrm{fib}(n - 1) \bmod M fib(n1)modM) 和 ( f i b ( n − 2 )   m o d   M ) \mathrm{fib}(n - 2) \bmod M) fib(n2)modM) 最多只有 M 2 M ^ 2 M2 种取值,所以在 M 2 M ^ 2 M2 次计算后一定出现过循环。

甚至更一般地,我们可以证明,无论取什么模数 M M M,最终模 M M M 下的斐波拉契数列都会是 0 , 1 , ⋯   , 0 , 1 , ⋯ 0, 1, \cdots, 0, 1, \cdots 0,1,,0,1,

现在,给你一个模数 M M M,请你求出最小的 n > 0 n > 0 n>0,使得 f i b ( n )   m o d   M = 0 , f i b ( n + 1 )   m o d   M = 1 \mathrm{fib}(n) \bmod M = 0, \mathrm{fib}(n + 1) \bmod M = 1 fib(n)modM=0,fib(n+1)modM=1

输入格式

输入一行一个正整数 M M M

输出格式

输出一行一个正整数 n n n

样例 #1

样例输入 #1

2

样例输出 #1

3

样例 #2

样例输入 #2

6

样例输出 #2

24

提示

样例 1 解释

斐波拉契数列为 0 , 1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 , ⋯ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, \cdots 0,1,1,2,3,5,8,13,21,34,,在对 2 2 2 取模后结果为 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , ⋯ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, \cdots 0,1,1,0,1,1,0,1,1,0,

我们可以发现,当 n = 3 n = 3 n=3 时, f ( n )   m o d   2 = 0 , f ( n + 1 )   m o d   2 = 1 f(n) \bmod 2= 0, f(n + 1) \bmod 2 = 1 f(n)mod2=0,f(n+1)mod2=1,也就是我们要求的 n n n 的最小值。

数据范围

对于 30 % 30\% 30% 的数据, M ≤ 18 M \leq 18 M18

对于 70 % 70\% 70% 的数据, M ≤ 2018 M \leq 2018 M2018

对于 100 % 100\% 100% 的数据, 2 ≤ M ≤ 706150 = 2 \leq M \leq 706150= 2M706150=0xAC666

提示

如果你还不知道什么是取模 (   m o d   ) (\bmod) (mod),那我也很乐意告诉你,模运算是求整数除法得到的余数,也就是竖式除法最终「除不尽」的部分,也即
a   m o d   M = k    ⟺    a = b M + k   ( M > 0 , 0 ≤ k < M ) a \bmod M =k \iff a = bM + k\ (M > 0, 0 \leq k < M) amodM=ka=bM+k (M>0,0k<M)
其中 a , b , k a, b, k a,b,k 都是非负整数。

如果你使用 C / C++,你可以使用 % 来进行模运算。

如果你使用 Pascal,你可以使用 mod 来进行模运算。

代码

M = int(input())

a = b = 1
i = 1
while a != 0 or b != 1:
    i += 1
    a, b = b, (a + b) % M

print(i)

03 [NOIP2011 提高组] 铺地毯

题目描述

为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有 n n n 张地毯,编号从 1 1 1 n n n。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。

地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。

输入格式

输入共 n + 2 n + 2 n+2 行。

第一行,一个整数 n n n,表示总共有 n n n 张地毯。

接下来的 n n n 行中,第 i + 1 i+1 i+1 行表示编号 i i i 的地毯的信息,包含四个整数 a , b , g , k a ,b ,g ,k a,b,g,k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标 ( a , b ) (a, b) (a,b) 以及地毯在 x x x 轴和 y y y 轴方向的长度。

n + 2 n + 2 n+2 行包含两个整数 x x x y y y,表示所求的地面的点的坐标 ( x , y ) (x, y) (x,y)

输出格式

输出共 1 1 1 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出 -1

样例 #1

样例输入 #1

3
1 0 2 3
0 2 3 3
2 1 3 3
2 2

样例输出 #1

3

样例 #2

样例输入 #2

3
1 0 2 3
0 2 3 3
2 1 3 3
4 5

样例输出 #2

-1

提示

【样例解释 1】

如下图, 1 1 1 号地毯用实线表示, 2 2 2 号地毯用虚线表示, 3 3 3 号用双实线表示,覆盖点 ( 2 , 2 ) (2,2) (2,2) 的最上面一张地毯是 3 3 3 号地毯。

【数据范围】

对于 30 % 30\% 30% 的数据,有 n ≤ 2 n \le 2 n2
对于 50 % 50\% 50% 的数据, 0 ≤ a , b , g , k ≤ 100 0 \le a, b, g, k \le 100 0a,b,g,k100
对于 100 % 100\% 100% 的数据,有 0 ≤ n ≤ 1 0 4 0 \le n \le 10^4 0n104, 0 ≤ a , b , g , k ≤ 10 5 0 \le a, b, g, k \le {10}^5 0a,b,g,k105

noip2011 提高组 day1 第 1 1 1 题。

代码

import numpy as np

n = int(input())

carpets = []

for carpet in range(1, n+1):
    carpets.append(list(map(int, input().split())))

x, y = map(int, input().split())

for index in range(len(carpets)-1, -1, -1):
    if x >= carpets[index][0] and x < carpets[index][0] + carpets[index][2]:
        if y >= carpets[index][1] and y < carpets[index][1] + carpets[index][3]:
            print(index+1)
            break
else:
    print(-1)

04 [NOIP2009 普及组] 多项式输出

题目描述

一元 n n n 次多项式可用如下的表达式表示:

f ( x ) = a n x n + a n − 1 x n − 1 + ⋯ + a 1 x + a 0 , a n ≠ 0 f(x)=a_nx^n+a_{n-1}x^{n-1}+\cdots +a_1x+a_0,a_n\ne 0 f(x)=anxn+an1xn1++a1x+a0,an=0

其中, a i x i a_ix^i aixi 称为 i i i 次项, a i a_i ai 称为 i i i 次项的系数。给出一个一元多项式各项的次数和系数,请按照如下规定的格式要求输出该多项式:

  1. 多项式中自变量为 x x x,从左到右按照次数递减顺序给出多项式。

  2. 多项式中只包含系数不为 0 0 0 的项。

  3. 如果多项式 n n n 次项系数为正,则多项式开头不出 + 号,如果多项式 n n n 次项系数为负,则多项式以 - 号开头。

  4. 对于不是最高次的项,以 + 号或者 - 号连接此项与前一项,分别表示此项系数为正或者系数为负。紧跟一个正整数,表示此项系数的绝对值(如果一个高于 0 0 0 次的项,其系数的绝对值为 1 1 1,则无需输出 1 1 1)。如果 x x x 的指数大于 1 1 1,则接下来紧跟的指数部分的形式为“ x b x^b xb”,其中 b b b x x x 的指数;如果 x x x 的指数为 1 1 1,则接下来紧跟的指数部分形式为 x x x;如果 x x x 的指数为 0 0 0,则仅需输出系数即可。

  5. 多项式中,多项式的开头、结尾不含多余的空格。

输入格式

输入共有 2 2 2

第一行 1 1 1 个整数, n n n,表示一元多项式的次数。

第二行有 n + 1 n+1 n+1 个整数,其中第 i i i 个整数表示第 n − i + 1 n-i+1 ni+1 次项的系数,每两个整数之间用空格隔开。

输出格式

输出共 1 1 1 行,按题目所述格式输出多项式。

样例 #1

样例输入 #1

5 
100 -1 1 -3 0 10

样例输出 #1

100x^5-x^4+x^3-3x^2+10

样例 #2

样例输入 #2

3 
-50 0 0 1

样例输出 #2

-50x^3+1

提示

NOIP 2009 普及组 第一题

对于100%数据, 0 ≤ n ≤ 100 0 \le n \le 100 0n100,$-100 \le 系数 系数 系数 \le 100$


upd 2022.8.1 \text{upd 2022.8.1} upd 2022.8.1:新增加一组 Hack 数据。

代码

n = int(input())
lst = list(map(int, input().split()))
strr = ''
for i in range(len(lst)):
    if i == len(lst) - 1:
        break
    if lst[i] > 1:  # 大于1就要写上前面呗
        if n == 1:
            strr += str(lst[i]) + "x+"
        else:
            strr += str(lst[i]) + "x^%d+" % n
    elif lst[i] == 1:  # 等于1的时候前面不就不写
        if n == 1:
            strr += "x+"
        else:
            strr += "x^%d+" % n
    elif lst[i] < -1:
        if n == 1:  # 多一个加号 就得删了
            strr = strr[:-1]
            strr += str(lst[i]) + "x+"
        else:
            strr = strr[:-1]
            strr += str(lst[i]) + "x^%d+" % n
    elif lst[i] == -1:
        if n == 1:
            strr = strr[:-1]
            strr += "-x+"
        else:
            strr = strr[:-1]
            strr += "-x^%d+" % n
    else:
        strr += ''  # 要是0不就是不写吗
    n -= 1  # 每次减一不就是次方吗

if lst[-1] == 0:  # 处理最后一个
    print(strr[:-1])
if lst[-1] > 0:
    strr += str(lst[-1])
    print(strr)
if lst[-1] < 0:
    strr = strr[:-1]
    strr += str(lst[-1])
    print(strr)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是丝豆呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值