python解决上n级台阶问题,步长为3k+1,k为任一自然数

Problem

竺竺为了追求漂亮温柔的学姐,决定走到学姐所在的第n级平台上,由于他心情欢快连跑带跳,他一次只能向上走1,4,7,10…(即3n+1)级台阶。竺竺想知道他有多少种方法走上这n级台阶,你能帮帮他吗?

Input

一行一个整数n(n<=10000),表示一共有n级台阶。

Output

一行一个整数,表示竺竺上台阶的方案数,结果对100003取余。

Sample Input

5

Sample Output

3

初步想法

def count(n),计算上n级台阶的方案数;
所有的方案按照最后一步的走法分类;
最后一步可能走1,4,7……,m;m是数列{3k+1}中不大于n的最大项;
那么按照加法原理:
c o u n t ( n ) = c o u n t ( n − 1 ) + c o u n t ( n − 4 ) + … … + c o u n t ( n − m ) count(n)=count(n-1)+count(n-4)+……+count(n-m) count(n)=count(n1)+count(n4)++count(nm)

代码一

def count(n):
	if n%3==0:   #先求得m
		m=i-2
	elif n%3==1:
 		m=i
	else:
		m=i-1
	if n<4:
		return 1    #递归出口
	else:
		s=sum([count(n-i) for i in range(1,m+3,3)])  #递归
		return s%100003
n=int(input())
print(count(n))
输入:50
输出:13886
耗时:54.8s

优化

递归显然是低效的,考虑逐项递推,来降低空间复杂度;
用字典键值对来存储(台阶数,方案数)

def count(n):
    l={0:1,1:1,2:1,3:1}   #字典存放--台阶数:方案数
    if n<4:
        return 1
    else:
        for i in range(4,n+1):   #求得{3k+1}数列中不大于i的最大项为m
            if i%3==0:
                m=i-2
            elif i%3==1:
                m=i
            else:
                m=i-1
            l[i]=sum([l[i-j] for j in range(1,m+3,3)])%100003   #同样的递推关系,用字典来操作
        return l[n]  #返回字典中键n的值
n=int(input())
print(cou(n))
输入:50;1000;10000,100000(除了这个程序其他都算不了十万)
输出:13886;56613;30763;37326
耗时:731ms;1.38s;5.29s;很久

另一种想法

换一种分类的方法,考虑走的步数;
假定走了m步,每一步走
3 k i + 1 , k i ∈ N , i = 1 , 2 , . . . , m 3k_i+1,k_i\in N,i=1,2, ...,m 3ki+1kiNi=1,2,...,m
那么就得到
∑ i = 1 m ( 3 k i + 1 ) = n \sum _{i=1}^m(3k_i+1)=n i=1m(3ki+1)=n
也就是
∑ i = 1 m k i = n − m 3 \sum _{i=1}^mk_i={{n-m}\over3} i=1mki=3nm
这个不定方程的解集的个数其实是很好求的。
这里要求 m ≡ n m o d    3 , 1 ≤ m ≤ n , m ∈ N ∗ m\equiv n \mod 3,1\leq m\leq n,m\in N^* mnmod31mn,mN方程才有解;
方程解集个数为 C n − m 3 + m − 1 m − 1 C_{{{n-m}\over 3} +m-1}^{m-1} C3nm+m1m1
(这是个典型的组合问题,可以参考以下文章 链接🔗
在这里插入图片描述

接下来就是简单的编程问题了:

代码二

from scipy.special import comb   #借用scipy库计算组合数
def cou(n):
    sum_answer = 0
    for m in range(n,0,-3):  #m其实就是n-3k
        sum_answer += comb((n+2*m-3)/3,(n-m)/3,True)   
           #这里True参数表示结果用int表示,否则默认返回float
    return sum_answer%100003
n=int(input())
print(cou(n))
输入:50;1000;10000
输出:13886;56613;30763
耗时:728ms;1.36s;5.05s

实际上计算更大的数据时用组合数的方法就不再占优势(也可能是py的局限性),但是数学上岂不美哉~



以上

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值