腾讯2018秋招正式笔试题目——拼凑硬币

11 篇文章 0 订阅
2 篇文章 0 订阅

时间限制:(每个case)2s      空间限制:128MB

小Q十分富有,拥有非常多的硬币,小Q拥有的硬币是有规律的,对于所有的非负整数K,小Q恰好各有两个面值为2^K的硬币,所以小Q拥有的硬币就是1,1,2,2,4,4,8,8,…。小Q有一天去商店购买东西需要支付n元钱,小Q想知道有多少种方案从他拥有的硬币中选取一些拼凑起来恰好是n元(如果两种方案某个面值的硬币选取的个数不一样就考虑为不一样的方案)。

输入:

输入包括一个整数n(1<=n<=10^18),表示小Q需要支付多少钱。注意n的范围。

输出:

输出一个整数,表示小Q可以拼凑出n元钱放的方案数。

【请注意:javascrip语言不支持调试,请同学们优先考虑使用其他语言,谢谢】

样例输入:6

样例输出:3


数位dp,将n表示成二进制,从为1的位置向后转移。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=200+10;
int dp[maxn];
int nxt[maxn],pos[maxn];
int inx,res;
int dfs(int x){
    if(x==-1)return 1;
    if(dp[x]!=0)return dp[x];
    dp[x]+=dfs(nxt[x]);
    for(int i=1;i<x;i++){
        if(pos[i]==1)continue;
        dp[x]+=dfs(nxt[i]);
    }
    return dp[x];
}
signed main(){
    int n;
    scanf("%lld",&n);
    res=-1;
    while(n){
        pos[++inx]=n%2;
        nxt[inx]=res;
        if(n&1)res=inx;
        n/=2;
    }
    printf("%lld\n",dfs(inx));
    return 0;
}

在别人博客中看见了更加简单的方法,用位运算+分治,将0看成是用了0次或者2次,1表示自己用了一次或者后面用了两次。

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int maxn=200+10;
int solve(int n){
    if(n==0)return 0;
    if(n==1)return 1;
    if(n==2)return 2;

    if(n&1){
        return solve(n>>1);
    }
    return solve(n>>1)+solve((n-2)>>1);
}
signed main(){
    int n;
    scanf("%lld",&n);
    printf("%lld\n",solve(n));
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值