魔法深渊

魔法深渊

http://www.nowcoder.com/questionTerminal/55e34723b1d34c42af83b39de2395408

题目难度:二星
考察点:动态规划、预处理

方法1:暴力、动态规划

  1. 分析:

这个题很像之前的跳台阶:一共有n个台阶,青蛙只能跳1阶或者是2阶,问有多少种跳法?
跳台阶思路如下:
假设青蛙跳n个台阶的跳法为f(n)那么:
如果第一次跳的是1阶,那么剩下的n-1个台阶,跳法是f(n-1)
如果第一次跳的是2阶,那么剩下的n-2个台阶,跳法是f(n-2)
由此可得:f(n) = f(n-1) + f(n-2)
当n=1时,f(1) = 1
当n=2时,f(2) = 2
至此,跳台阶问题已经解决。
对于这道题来说的话,我们可以借助之前的想法,假设月神有f(n)种方法能够跳出深渊,那么就有:
如果第一次跳的是2^0阶,那么剩下的n-2^0个台阶,就有f(n-2^0)种跳法。
如果第一次跳的是2^1阶,那么剩下的n-2^1个台阶,就有f(n-2^1)种跳法。
...
如果第一次跳的是2^k阶,那么剩下的n-2^k个台阶,就有f(n-2^k)种跳法。
其中k为不超过n的2的次幂的指数最大值。
那么由此可得:f(n) = f(n-2^0) + f(n-2^1) + ... + f(n-2^k)
当n=0时,f(0) = 1。

算法实现:
(1). 用一个数组p表示2的幂,其中p[i]=2^i
(2). 输入n,然后从1遍历到n,在来一个内层循环j表示2^j,然后如果i >= p[j], dp[i] += dp[i-p[j]],不要忘记取模
(2). 输出结果dp[n]。

2. 复杂度分析:

时间复杂度:O(n^2log(n))
空间复杂度:O(n)


3. 代码:

#include 
using namespace std;
typedef long long LL;
int p[10] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512};
const int MAXN = 1e3+5;
const int MOD = 1e9+3;
LL dp[MAXN];
int main() {
 int m; cin>>m;
 while(m--) {
     int n; cin>>n;
     memset(dp, 0, sizeof dp);
     dp[0] = 1;
     for(int i=1; i<=n; i++) {
         for(int j=0; j<10; j++) {
             if(i < p[j]) break;
             dp[i] = (dp[i] + dp[i-p[j]]) % MOD;
         }
     }
     cout<<dp[n]<<endl;
 }
 return 0;
}

方法2:预处理、动态规划


  1. 分析:

    其实在上述的代码中,我们其实没有必要在m层循环中,每次都计算一遍dp[n],这样是浪费时间的,我们可以提前预处理一下dp[n]的计算方法,这样在循环中只需要输入一个n,输出一个dp[n]即可,具体详见代码。

  2. 复杂度分析:

    时间复杂度:O(max(nlog(n), m))
    空间复杂度:O(n)
  3. 代码:

    #include 
    using namespace std;
    typedef long long LL;
    int p[10] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512};
    const int MAXN = 1e3+5;
    const int MOD = 1e9+3;
    LL dp[MAXN];
    void Init() {
     dp[0] = 1;
     for(int i=1; i<MAXN; i++) {
         for(int j=0; j<10; j++) {
             if(i < p[j]) break;
             dp[i] = (dp[i] + dp[i-p[j]]) % MOD;
         }
     }
    }
    int main() {
     int m; cin>>m;
     Init();
     while(m--) {
         int n; cin>>n;
         cout<<dp[n]<<endl;
     }
     return 0;
    }
全部评论

相关推荐

刚刷到字节跳动官方发的消息,确实被这波阵仗吓了一跳。在大家还在纠结今年行情是不是又“寒冬”的时候,字节直接甩出了史上规模最大的转正实习计划——ByteIntern。咱们直接看几个最硬的数,别被花里胡哨的宣传词绕晕了。首先是“量大”。全球招7000多人是什么概念?这几乎是把很多中型互联网公司的总人数都给招进来了。最关键的是,这次的资源分配非常精准:研发岗给了4800多个Offer,占比直接超过六成。说白了,字节今年还是要死磕技术,尤其是产品和AI领域,这对于咱们写代码的同学来说,绝对是今年最厚的一块肥肉。其次是大家最关心的“转正率”。官方直接白纸黑字写了:整体转正率超过50%。这意味着只要你进去了,不划水、正常干,每两个人里就有一个能直接拿校招Offer。对于2027届(2026年9月到2027年8月毕业)的同学来说,这不仅是实习,这简直就是通往大厂的快捷通道。不过,我也得泼盆冷水。坑位多,不代表门槛低。字节的实习面试出了名的爱考算法和工程实操,尤其是今年重点倾斜AI方向,如果你简历里有和AI相关的项目,优势还是有的。而且,转正率50%也意味着剩下那50%的人是陪跑的,进去之后的考核压力肯定不小。一句话总结:&nbsp;27届的兄弟们,别犹豫了。今年字节这是铁了心要抢提前批的人才,现在投递就是占坑。与其等到明年秋招去千军万马挤独木桥,不如现在进去先占个工位,把转正名额攥在手里。
喵_coding:别逗了 50%转正率 仔细想想 就是转正与不转正
字节7000实习来了,你...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务