🍑 蓝桥 二进制问题
输入
7 2
输出
3
👨🏫 大佬的数位DP
import java.util.*;
public class Main {
static final int N = 200;
static long[][][] f = new long[N][2][N];
static int[] a = new int[N];
public static long dfs(int w, int zt, int sum, int k) {
long ans = 0;
if (w == 0) return sum == k ? 1 : 0;
if (f[w][zt][sum] != -1) return f[w][zt][sum];
for (int i = 0; i < 2; ++i) {
if (zt == 1 && i > a[w]) break;
ans += dfs(w-1, zt!= 0&&(i==a[w])?1:0, sum+i, k);
}
return f[w][zt][sum] = ans;
}
public static long digit(long x, int k) {
int cnt = 0;
Arrays.fill(a, 0);
for(int i = 0; i < N; i++)
for(int j = 0; j < 2; j++)
Arrays.fill(f[i][j], -1);
while(x != 0) {
a[++cnt] = (int) (x % 2);
x /= 2;
}
return dfs(cnt, 1, 0, k);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long n = sc.nextLong();
int k = sc.nextInt();
System.out.println(digit(n, k));
}
}
🍑 暴搜 (40%)
注意:数据范围过大 开 long
import java.util.Scanner;
public class Main
{
static long N, K, cnt;
static long ans = 0;
/**
* @param u 表示当前所在的位
* @param k 表示当前数二进制位上有多少个 1
* @param x 表示当前的数值
*/
static void dfs(int u, int k, String x)
{
if (k > K)//可行性剪枝
return;
if (!x.equals("") && Long.parseLong(x, 2) > N)//可行性剪枝
return;
// System.out.println(x);
if (u == cnt)
{
if (k == K)//递归出口
ans++;
return;
}
dfs(u + 1, k + 1, x + "1");
dfs(u + 1, k, x + "0");
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
K = sc.nextInt();
long t = N;
// 计算 n 的数位
while (t != 0)
{
t >>= 1;
cnt++;
}
dfs(0, 0, "");
System.out.println(ans);
}
}