东东在一本古籍上看到有一种神奇数,如果能够将一个数的数字分成两组,其中一组数字的和等于另一组数字的和,我们就将这个数称为神奇数。例如 242 就是一个神奇数,我们能够将这个数的数字分成两组,分别是 {2,2} 以及 {4} ,而且这两组数的和都是 4 .东东现在需要统计给定区间中有多少个神奇数,即给定区间 [l, r] ,统计这个区间中有多少个神奇数,请你来帮助他。
数据范围:
, 
输入包括一行,一行中两个整数l和r(1 ≤ l, r ≤ 10^9, 0 ≤ r - l ≤ 10^6),以空格分割
输出一个整数,即区间内的神奇数个数
1 50
4
11 11
1
import java.util.Arrays;
import java.util.Scanner;
/**
* 京东2018秋招Android
* 神奇数
* 东东在一本古籍上看到有一种神奇数,如果能够将一个数的数字分成两组,其中一组数字的和等于另一组数字的和,
* 我们就将这个数称为神奇数。例如242就是一个神奇数,我们能够将这个数的数字分成两组,分别是{2,2}以及{4},
* 而且这两组数的和都是4.东东现在需要统计给定区间中有多少个神奇数,即给定区间[l, r],统计这个区间中有多
* 少个神奇数,请你来帮助他。
* 输入描述:
* 输入包括一行,一行中两个整数l和r(1 ≤ l, r ≤ 10^9, 0 ≤ r - l ≤ 10^6),以空格分割
* <p>
* <p>
* 输出描述:
* 输出一个整数,即区间内的神奇数个数
* <p>
* 输入例子1:
* 1 50
* <p>
* 输出例子1:
* 4
*/
public class MagicNumber {
/**
* 首先判断数组能否被平分,即数组分割问题,
* dp[i][j]
* 表示数组前 i
* 个数字能否求和得到 j
* 则
* dp[i][j]=dp[i−1][j]||dp[i−1][j−array[i]]
* 其中||是逻辑或运算。
* 优化:
* 1、若sum(array)为奇数,直接返回false
* 2、使用逆序循环将dp数组简化为一维数组
*/
public static boolean isMagic(int[] nums, int sum) {
int len = nums.length;
if (sum % 2 != 0)
return false;
int mid = sum / 2;
int[] dp = new int[mid + 1];
dp[0] = 1;
for (int i = 0; i < len; i++) {
for (int j = mid; j > 0; j--) {
if (j >= nums[i] && nums[i] != -1)
dp[j] = Math.max(dp[j], dp[j - nums[i]]);
}
}
if (dp[mid] > 0)
return true;
else
return false;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int l = sc.nextInt();
int r = sc.nextInt();
int result = 0;
for (int i = l; i <= r; i++) {
int num = i;
int[] nums = new int[10];
int sum = 0;
Arrays.fill(nums, -1);
int index = 0;
while (num > 0) {
int temp = num % 10;
nums[index++] = temp;
sum += temp;
num = num / 10;
}
if (isMagic(nums, sum)) {
result++;
}
}
System.out.println(result);
}
}
#include <iostream>#include <vector> #include <algorithm> using namespace std; bool judge(vector<int>& nums,int sum){ if(sum%2!=0) //如果累加和为奇数,直接false return false; int n=nums.size(); int target=sum/2; //目标累加和 vector<bool> dp(target+1,false); //dp[i][j]为前i个数的累加和能否为j,简化为一维数组 dp[0]=true; for(int i=1;i<=n;++i) for(int j=target;j>=nums[i];--j) //0-1背包问题,逆序循环 dp[j]=dp[j-nums[i]] || dp[j]; return dp[target]; } vector<int> get_num(int i){ //取出每一位数字 vector<int> res; while(i){ res.push_back(i%10); i/=10; } return res; } int main(){ int l,r; cin>>l>>r; int cnt=0; for(int i=l;i<=r;++i){ vector<int> nums=get_num(i); int sum=accumulate(nums.begin(),nums.end(),0); if(judge(nums,sum)) cnt++; } cout<<cnt; return 0; }
#include <iostream> #include <vector> #include <algorithm> using namespace std; bool IsNum(int &in){ vector<int> arry; int num=in; int half=0; while(num){//将数字打散存入arry数组 arry.push_back(num%10); half+=num%10; num/=10; } if (half%2!=0) return false; half/=2; vector<int> dp(half+1); //之后这一小段用的是01背包,判断能装下最大的数和一半是否相等。 for (int i=0;i<arry.size();i++){ for(int j=half;j>=arry[i];j--){ dp[j]=max(dp[j],dp[j-arry[i]]+arry[i]); } } return dp[half]==half; } int main() { int l,r; cin>>l>>r; int count=0; for(int i=l;i<=r;i++){ if(IsNum(i)) count++;//如果是神奇数,计数+1 } cout<<count<<endl; return 0; }
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] params = br.readLine().split(" "); int left = Integer.parseInt(params[0]); int right = Integer.parseInt(params[1]); int count = 0; for(int num = left; num <= right; num++){ char[] digits = String.valueOf(num).toCharArray(); int[] arr = new int[digits.length]; int sum = 0; for(int i = 0; i < arr.length; i++) { arr[i] = digits[i] - '0'; sum += arr[i]; } if(isValid(arr, sum)) count++; } System.out.println(count); } private static boolean isValid(int[] nums, int sum) { if(sum % 2 != 0) return false; int target = sum >> 1; int n = nums.length; return recurrent(nums, 0, target) > 0; } private static int recurrent(int[] nums, int depth, int rest) { if(depth == nums.length) return rest == 0? 1: 0; if(rest == 0) return 1; if(rest < 0) return 0; return recurrent(nums, depth + 1, rest - nums[depth]) + recurrent(nums, depth + 1, rest); } }
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.Arrays; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] params = br.readLine().split(" "); int left = Integer.parseInt(params[0]); int right = Integer.parseInt(params[1]); int count = 0; for(int num = left; num <= right; num++){ char[] digits = String.valueOf(num).toCharArray(); int[] arr = new int[digits.length]; int sum = 0; for(int i = 0; i < arr.length; i++) { arr[i] = digits[i] - '0'; sum += arr[i]; } if(isValid(arr, sum)) count++; } System.out.println(count); } private static boolean isValid(int[] nums, int sum) { if(sum % 2 != 0) return false; int target = sum >> 1; int n = nums.length; int[][] memory = new int[n + 1][target + 1]; return recurrent(nums, 0, target, memory) > 0; } private static int recurrent(int[] nums, int depth, int rest, int[][] memory) { if(depth == nums.length) return rest == 0? 1: 0; if(rest == 0) return 1; if(rest < 0) return 0; if(memory[depth][rest] > 0) return memory[depth][rest]; memory[depth][rest] = recurrent(nums, depth + 1, rest - nums[depth], memory) + recurrent(nums, depth + 1, rest, memory); return memory[depth][rest]; } }
#include <bits/stdc++.h> using namespace std; bool F(int x){ int k=0, s=0, t, a[11]; while(x){ t = x%10; if(t){ a[k++] = t; s += t; } x /= 10; } if(s&1) return 0; s >>= 1; int dp[s+1]; memset(dp, 0, sizeof(dp)); dp[0] = 1; for(int i=0;i<k;i++) for(int j=s;j>=a[i];j--) dp[j] = dp[j] || dp[j-a[i]]; return dp[s]; } int main(){ int l, r, cnt=0; scanf("%d%d", &l, &r); for(int i=l;i<=r;i++) if(F(i)) cnt++; printf("%d\n", cnt); return 0; }
思路:设数X,先求出X的每位数存到vector中,再求出X每位数之和sum, 若为奇数则舍弃, 若为偶数则判断是否是神奇数,若是神奇数,则vector中必存在若干个数的和为sum/2, 所以只需判断sum/2 减去vector中的数是否为0即可 ps:感觉思路没啥问题,但只通过40%,很悲伤 #include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int l,r; cin>>l>>r; int total = 0; for(int i = l; i <= r; i++) { int n=i; int sum = 0; int half = 0; vector<int> vec; while(n > 0) { vec.push_back(n % 10); sum += n % 10; n = n / 10; } if(sum % 2 == 0) { half = sum / 2; sort(vec.begin(),vec.end()); for(int j=vec.size()-1;j>=0;j--) { if(half>=vec[j]) { half=half-vec[j]; if(half==0) { total++; break; } } } } } cout << total; return 0; } //经好心人指出,已改正 #include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int l,r; cin>>l>>r; int total = 0; for(int i = l; i <= r; i++) { int n=i; int sum = 0; int half = 0; vector<int> vec; while(n > 0) { vec.push_back(n % 10); sum += n % 10; n = n / 10; } if(sum % 2 == 0) { half = sum / 2; vector<int> re(half+1); for(int i=0;i<vec.size();i++) { for(int j=half;j>=vec[i];j--) { re[j]=max(re[j],re[j-vec[i]]+vec[i]); } } if(half==re[half]) { total++; } } } cout << total; return 0; }
import java.util.*; public class Main { private static Map<Integer, Boolean> map = new HashMap<>(); public static void main(String[] args) { Scanner sc = new Scanner(System.in); int l = sc.nextInt(), r = sc.nextInt(); int ans = 0; for (int i=l; i<=r; i++) { if (isMiraculous(i)) { ans++; } } System.out.println(ans); } private static boolean isMiraculous(int p) { String sp = String.valueOf(p); int n = sp.length(); char[] sa = sp.toCharArray(); Arrays.sort(sa); Integer sorted = Integer.valueOf(new String(sa)); if (map.containsKey(sorted)) { return map.get(sorted); } int in = sp.chars().map(c -> c -'0').sum(); if (in % 2 != 0) { map.put(sorted, false); return false; } int[] ia = sp.chars().map(c -> c -'0').toArray(); for (int i=1; i<=(1<<n); i++) { int tmp = i; int left = 0 ,right = 0; for (int j=0; j<n; j++) { if (((tmp >> j) & 1)== 0) { left+=ia[j]; } else { right+=ia[j]; } } if (left == right) { map.put(sorted, true); return true; } } map.put(sorted, false); return false; } }
import java.util.Scanner;
public class Main {
public static void main(String[] args) { Main test = new Main(); Scanner in = new Scanner(System.in); int l, n; l = in.nextInt(); n = in.nextInt(); in.close(); int sum = 0; for(int i = l; i <= n; i++){ if(test.checkNumber(i)) sum++; } System.out.println(sum); } private boolean checkNumber(int N){ int B_sum = 0,n = N,cur = 0; int[] str = new int[10]; while(n > 0){ str[cur] = n % 10; B_sum += str[cur]; cur++; n /= 10; } if((B_sum % 2) != 0) return false; B_sum /= 2; boolean[] f = new boolean[41]; f[str[0]] = true; for(int i = 1; i < cur; i++){ int value = str[i]; for(int j = 40; j >= 0; --j){ //只能逆序循环,因为下一行会把f[j+value]改为true if(f[j] && j + value <= 40) //顺序循环的话,j=k时,将k+value设为true,当j读到k+value时就出问题了 f[j + value] = true; } if(f[B_sum]) { return true; } } return false; }
}
import java.util.*; import java.io.*; public class Main{ public static void main(String[] args) throws Exception{ BufferedReader df=new BufferedReader(new InputStreamReader(System.in)); String sd; while((sd=df.readLine())!=null){ String[] ds=sd.split(" "); int end=Integer.valueOf(ds[1]); if(end<=10){ System.out.println(0); return; } int num=0; int start1=Integer.valueOf(ds[0]); int start =start1<=10?10:start1; for(int i=start;i<=end;i++){ if(gg(i)) { num++; } } System.out.println(num); } } public static boolean gg(int h){ List<Integer> res=new ArrayList<Integer>(); int sum=0; while(h!=0){ int h1=h%10; sum+=h1; res.add(h1); h=h/10; } if(sum%2==1){ return false; } sum=sum/2; boolean[] res1=new boolean[sum+1]; res1[0]=true; for(Integer d:res){ for(int i=sum;i>=0;i--){ if(i>=d){ res1[i]=res1[i-d]|res1[i]; } } } return res1[sum]; } }
import java.util.*; public class Main{ public static void main(String[] args){ // 01背包 Scanner scan = new Scanner(System.in); int l = scan.nextInt(); int r = scan.nextInt(); int ans = 0; for(int i=l;i<=r;++i){ if(check(i)) { ++ans; //System.out.println(i); } } System.out.println(ans); } private static boolean check(int x){ ArrayList<Integer>list = new ArrayList<>(); int v = 0; while(x!=0){ list.add(x%10); v+=x%10; x/=10; } if((v&1)==1) return false; v/=2; int[] dp = new int[v+1]; dp[0] = 1; for(int i=0;i<list.size();++i){ int t = list.get(i); for(int j=v;j>=t;j--){ if(dp[j-t]!=0) dp[j]=1; } } return dp[v]==1; } }
//方法1每个数暴力搜索
//方法2记忆化搜索
//方法3动态规划
//可能是状态不多或是每个数初始化dp数组费时,测下来发现暴力搜索是最快的
#include <bits/stdc++.h> using namespace std; #define INIT() ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int a[15]; //dp用 int dp[50]; //记忆化搜索用 bool DP[15][50]; bool vis[15][50]; //暴力搜索 bool dfs(int i,int n,int w){ if(i==n) return w==0; if(w<a[i]) return dfs(i+1,n,w); return dfs(i+1,n,w-a[i])||dfs(i+1,n,w); } //方法1,暴力搜索 bool dynamicP1(int n, int w){ return dfs(0,n,w); } //记忆化搜索 bool ms(int i,int n,int w){ if(vis[i][w]) return DP[i][w]; vis[i][w] = 1; if(i==n) return DP[i][w] = (w==0); if(w<a[i]) return DP[i][w] = dfs(i+1,n,w); return DP[i][w] = (dfs(i+1,n,w-a[i])||dfs(i+1,n,w)); } //方法2:记忆化 bool dynamicP2(int n, int w){ memset(DP,0,sizeof(DP)); memset(vis,0,sizeof(vis)); return ms(0,n,w); } //方法3,直接dp bool dynamicP3(int n, int w){ memset(dp,0,sizeof(dp)); dp[0] = 1; for(int i=0;i<n;i++){ for(int j=w;j>=a[i];j--) dp[j] = dp[j]||dp[j-a[i]]; } return dp[w]; } bool judge(int number){ int cnt = 0, sum = 0; while(number){ int tmp = number%10; if(tmp) { a[cnt++] = tmp; sum+=tmp; } number/=10; } if(sum&1) return 0; return dynamicP3(cnt,sum>>1); } void solve(int l,int r){ int ans = 0; for(int i=l;i<=r;i++){ if(judge(i)) ans++; } cout<<ans<<endl; } int main() { INIT() int l,r; while(cin>>l>>r){ solve(l,r); } return 0; }
import java.util.Scanner; public class Main{ public static boolean isJJ(int num) { int[] arr = new int[11]; int index = 0; int sum = 0; for( ; num > 0; index++) { arr[index] = num % 10; sum += arr[index]; num /= 10; } if(sum % 2 != 0) return false; return isKK(arr, sum / 2, index); } public static boolean isKK(int[] arr, int sum, int index) { if(sum == 0) return true; if(index < 0 || sum < 0) return false; return isKK(arr, sum - arr[index], index - 1) || isKK(arr, sum, index - 1); } public static void main(String[] args) { Scanner in = new Scanner(System.in); int l = in.nextInt(); int r = in.nextInt(); int count = 0; for(int i = l; i <= r; i++) { if(isJJ(i)) count++; } System.out.println(count); } }