美文网首页
[44]神奇数-京东2018秋

[44]神奇数-京东2018秋

作者: jdzhangxin | 来源:发表于2018-11-08 19:52 被阅读26次

1.题目描述

东东在一本古籍上看到有一种神奇数,如果能够将一个数的数字分成两组,其中一组数字的和 等于另一组数字的和,我们就将这个数称为神奇数。例如242就是一个神奇数,我们能够将这个数的数字分 成两组,分别是{2,2}以及{4},而且这两组数的和都是4.东东现在需要统计给定区间中有多少个神奇数,即 给定区间[l,r],统计这个区间中有多少个神奇数,请你来帮助他。

  • 输入描述:
    输入包括一行,一行中两个整数l 和 r(1 ≤ l, r ≤ 10^9, 0 ≤ r - l ≤ 10^6),以空格分割 输出描述:
    输出一个整数,即区间内的神奇数个数
  • 输入示例:
    1 50 
    
  • 输出示例:
    4
    

2.题目解析

  1. 要把数字按位转化成数组。
  2. 每位数字累计求和
  3. 数组中元素和是否能累加成半和。(01背包问题)

3.参考答案

自顶而下递归

#include <bits/stdc++.h> 
using namespace std; 
bool IsMagic(int i,int sum,int* nums){
    if(0 == sum) return true;
    if(0 > sum) return false;
    if(i < 0) return false;
    
    return IsMagic(i-1,sum-nums[i],nums)
         ||IsMagic(i-1,sum,nums);
}
bool check(int num) { 
    int nums[11]; // 把数字n按位存到s中
    int i = 0; // 下标
    int sum = 0; // 每位数字求和
    while(num > 0) { 
        nums[i] = num % 10; // 获取并保存每位数字 
        sum += nums[i++]; // 每位数字累计求和
        num /= 10; // 除去个位数字
    }
    // 每位数和是奇数,则肯定不是神奇数
    if(sum%2) return false;
    // 从每位数字中取出数字和是否为和的一半
    return IsMagic(i-1,sum/2,nums); 
} 
 
int main() { 
    int l = 0;
    int r = 0;
    scanf("%d%d",&l,&r);
    int res = 0; 
    for(int i = l; i <= r; ++i) { // 遍历[l,r]中所有数字
        if(check(i)) ++res; 
    } 
    printf("%d\n",res); 
    return 0;
}

自顶而下递归(备忘录法/记忆化搜索)

#include <bits/stdc++.h> 
using namespace std; 
bool IsMagic(int i,int sum,int* nums,vector<bool>* dp){
    if(0 == sum) return true;
    if(0 > sum) return false;
    if(i < 0) return false;
    if(false != dp[i][sum]) return dp[i][sum];
    return dp[i][sum] = IsMagic(i-1,sum-nums[i],nums,dp)
         ||IsMagic(i-1,sum,nums,dp);
}
bool check(int num) { 
    int nums[11]; // 把数字n按位存到s中
    int i = 0; // 下标
    int sum = 0; // 每位数字求和
    while(num > 0) { 
        nums[i] = num % 10; // 获取并保存每位数字 
        sum += nums[i++]; // 每位数字累计求和
        num /= 10; // 除去个位数字
    }
    // 每位数和是奇数,则肯定不是神奇数
    if(sum%2) return false;
    // 从每位数字中取出数字和是否为和的一半  
    vector<bool> dp[i];
    fill_n(dp,i,vector<bool>(sum/2+1,false));
    return IsMagic(i-1,sum/2,nums,dp); 
} 
 
int main() { 
    int l = 0;
    int r = 0;
    scanf("%d%d",&l,&r);
    int res = 0; 
    for(int i = l; i <= r; ++i) { // 遍历[l,r]中所有数字
        if(check(i)) ++res; 
    } 
    printf("%d\n",res); 
    return 0;
}

自底而上递推

#include <bits/stdc++.h> 
using namespace std; 
bool IsMagic(int i,int sum,int* nums,vector<bool>* dp){
    for(int idx=1;idx<=i;++idx){
        for(int s=0;s<=sum;++s){
           if(s-nums[idx] == 0){
               dp[idx][s] = true;
           }else if(s-nums[idx]>0){
               dp[idx][s] = dp[idx-1][s-nums[idx]]||dp[idx-1][s];    
           }else{
               dp[idx][s] = dp[idx-1][s];
           }            
        }
    }
    return dp[i][sum];
}
bool check(int num) { 
    int nums[11]; // 把数字n按位存到s中
    int i = 0; // 下标
    int sum = 0; // 每位数字求和
    while(num > 0) { 
        nums[i] = num % 10; // 获取并保存每位数字 
        sum += nums[i++]; // 每位数字累计求和
        num /= 10; // 除去个位数字
    }
    // 每位数和是奇数,则肯定不是神奇数
    if(sum%2) return false;
    // 从每位数字中取出数字和是否为和的一半  
    vector<bool> dp[i];
    fill_n(dp,i,vector<bool>(sum/2+1,false));
    return IsMagic(i-1,sum/2,nums,dp); 
} 
 
int main() { 
    int l = 0;
    int r = 0;
    scanf("%d%d",&l,&r);
    int res = 0; 
    for(int i = l; i <= r; ++i) { // 遍历[l,r]中所有数字
        if(check(i)) ++res; 
    } 
    printf("%d\n",res); 
    return 0;
}

滚动数组优化

#include <bits/stdc++.h> 
using namespace std; 
bool IsMagic(int i,int sum,int* nums,bool* dp){
    for(int idx=1;idx<=i;++idx){
        for(int s=sum;s>=nums[idx];--s){
           if(s-nums[idx] == 0){
               dp[nums[idx]] = true;
           }else{
               dp[s] = dp[s-nums[idx]]||dp[s];    
           }            
        }
    }
    return dp[sum];
}
bool check(int num) { 
    int nums[11]; // 把数字n按位存到s中
    int i = 0; // 下标
    int sum = 0; // 每位数字求和
    while(num > 0) { 
        nums[i] = num % 10; // 获取并保存每位数字 
        sum += nums[i++]; // 每位数字累计求和
        num /= 10; // 除去个位数字
    }
    // 每位数和是奇数,则肯定不是神奇数
    if(sum%2) return false;
    // 从每位数字中取出数字和是否为和的一半  
    bool dp[sum/2+1];
    fill_n(dp,sum/2+1,false);
    return IsMagic(i-1,sum/2,nums,dp); 
} 
 
int main() { 
    int l = 0;
    int r = 0;
    scanf("%d%d",&l,&r);
    int res = 0; 
    for(int i = l; i <= r; ++i) { // 遍历[l,r]中所有数字
        if(check(i)) ++res; 
    } 
    printf("%d\n",res); 
    return 0;
}

牛客题目

相关文章

  • [44]神奇数-京东2018秋

    1.题目描述 东东在一本古籍上看到有一种神奇数,如果能够将一个数的数字分成两组,其中一组数字的和 等于另一组数字的...

  • 神奇数-(京东2018)

    题目:如果一个数的数字分为两组,其中一组数字的和等于另一组数字的和,这样的数成为神奇数;比如:242,满足:2+2...

  • [52]整除-京东2018秋

    1.题目描述 牛牛对整除非常感兴趣。牛牛的老师给他布置了一道题:牛牛的老师给出一个n,然后牛牛需要回答出能被1到n...

  • 京东TFS东北区面试分享

    京东物流2018年秋招TFS项目面试经历 本人大连海事大学2019年毕业小硕一名,在这里写下京东物流TFS项目整个...

  • 马庆洲:民俗画家张秋娣

    马庆洲:民俗画家张秋娣 马庆洲 2018-05-27 16:44 · 字数 1389 · 阅读 53 · 日记本 ...

  • 秋招备战准备,你跟上进度了吗?

    最近,有部分公司已经开始秋招,秋招的时间是越来越提前。2018年6月,很多大厂就已开始秋招(京东、华为、浦发银行等...

  • ==京东内推-神奇数-c++

    include include include inc...

  • [53]求幂-京东2018秋

    1.题目描述 东东对幂运算很感兴趣,在学习的过程中东东发现了一些有趣的性质: 9^3 = 27^2,2^10 = ...

  • 第一次尝试简书

    2018-8-25,8:44

  • 奇数和偶数的秘密(小学数学)

    1.任意两个奇数的和(或差),一定是偶数。 奇数+奇数=偶数 奇数–奇数=偶数 2.任意两个奇数的积,一定是奇数。...

网友评论

      本文标题:[44]神奇数-京东2018秋

      本文链接:https://www.haomeiwen.com/subject/dttpoftx.html