数的划分 分而治之 无数据 java

在这里插入图片描述
在这里插入图片描述
⭐ 简单分治(过样例)

① 算出 数 n 最后 划分 的 0 1 序列的长度(找规律)
② 划分的三个数 中间的数 肯定是 0 / 1 ,直接在区间中点记录结果
③ 递归处理左右区间,直到区间左右边界重合,也就是 0 1 已经放满了,此时的 x 就是结果该位置的 结果了

在这里插入图片描述

import java.util.Scanner;

public class 数的拆分
{
    
    
	static int N = (int) 1e8;
	static int[] a = new int[N];

	public static void main(String[] args)
	{
    
    
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int l = sc.nextInt();
		int r = sc.nextInt();

		int cnt = 0;// 记录 n 可以分出多少层
		for (int i = 0; i < 55; i++)
			if (n >= (1 << i) && n < (1 << i + 1))
			{
    
    
				cnt = i;
				break;
			}
//		System.out.println(cnt);
		int sum = 0;// sum 记录n 划分后的序列长度
		for (int i = 0; i <= cnt; i++)
			sum = sum * 2 + 1;

		mergeSort(n, 1, sum);

		long res = 0;
		for (int i = l; i <= r; i++)
			if (a[i] == 1)
				res++;
		System.out.println(res);
	}

	private static void mergeSort(int x, int l, int r)
	{
    
    
		if (l == r)
		{
    
    
			a[l] = x;
			return;
		}
		int t = x / 2;
		int m = x % 2;// m 不是 0 就是 1,所以直接放入数组即可
		int mid = l + r >> 1;
		a[mid] = m;

//		递归处理左右区间
		mergeSort(t, l, mid - 1);
		mergeSort(t, mid + 1, r);
	}
}

⭐ 剪枝 + 下标映射

package algorithm.lanQiao.分治;

import java.util.Scanner;

public class 数的拆分
{
    
    
	static int N = (int) 1e8;
	static Long L, R;
	static int[] a = new int[N];

	public static void main(String[] args)
	{
    
    
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		L = sc.nextLong();
		R = sc.nextLong();

		int cnt = 0;// 记录 n 可以分出多少层
		for (int i = 0; i < 51; i++)
			if (n >= (1 << i) && n < (1 << i + 1))
			{
    
    
				cnt = i;
				break;
			}
//		System.out.println(cnt);
		int sum = 0;// sum 记录n 划分后的序列长度
		for (int i = 0; i <= cnt; i++)
			sum = sum * 2 + 1;

		mergeSort(n, 1, sum);

		long res = 0;
		for (int i = 0; i <= R - L + 1; i++)
		{
    
    
//			System.out.print(a[i] + " ");
			if (a[i] == 1)
				res++;
		}
		System.out.println(res);
	}

	private static void mergeSort(int x, int l, int r)
	{
    
    
		// 非需要求解的区间(剪枝)
		int mid = l + r >> 1;
		if (l > R || r < L)
		{
    
    
			return;
		}
		if (l == r)
		{
    
    
			a[(int) (l - L + 1)] = x;
			return;
		}
		int t = x / 2;
		int m = x % 2;// m 不是 0 就是 1,所以直接放入数组即可
		a[(int) (mid - L) + 1] = m;

//		递归左右区间
		mergeSort(t, l, mid - 1);
		mergeSort(t, mid + 1, r);
	}
}

猜你喜欢

转载自blog.csdn.net/lt6666678/article/details/129878059