알고리즘 노트 연습 9.2 두 갈래 나무의 반복 문제 B: 두 갈래 나무

8232 단어 알고리즘 노트

알고리즘 노트 연습 문제 모음집


링크

제목


제목 설명
위에서 보듯이 정수 1, 2, 3.......로 특수한 두 갈래 나무를 이루었다.우리는 이미 이 두 갈래 나무의 마지막 결점이 n이라는 것을 안다.현재의 문제는 결점 m가 있는 자수에 모두 몇 개의 결점이 포함되어 있느냐는 것이다.
예를 들어 n=12, m=3 그러면 위 그림의 결점 13, 14, 15 및 뒤의 결점은 모두 존재하지 않는다. 결점 m가 있는 자수에 포함된 결점은 3, 6, 7, 12이기 때문에 결점 m가 있는 자수에는 모두 4개의 결점이 있다.
입력 입력 데이터는 여러 줄을 포함하고 각 줄은 두 개의 정수 m, n(1<=m<=n<=100000000)을 포함하는 테스트 데이터를 제공한다.마지막 테스트 데이터에는 두 개의 0이 포함되어 있으며, 입력의 끝을 표시하며, 이 데이터는 처리할 필요가 없다.
출력은 모든 테스트 데이터에 대해 한 줄을 출력합니다. 이 줄은 하나의 정수를 포함하고 결점 m가 있는 하위 트리에 포함된 결점의 수를 제시합니다.
샘플 입력
3 7
142 6574
2 754
0 0

샘플 출력
3
63
498

생각


만약에 한 결점의 번호가 kkk라고 가정하면 분명히 그의 왼쪽 아이 결점 번호는 2k2k이고 오른쪽 아이 결점 번호는 2k+12k+12k+1이다.
그러면 무한히 아래로 뻗은 만 두 갈래 나무 안에서 임의로 결점 번호r를 취하고 이 노드를 루트 노드로 하는 서브트리를 설정한다. nn층(루트 노드는 0 0층) 노드 번호의 범위는 폐구간 [l e ft, r i g h t] [left,\right] [left,right], l e ft left의 값은 r *= 2 nn번 교체된 후r여야 한다.r i g h t right right의 값은 r = r * 2 + 1 nnn회 교체된 후r여야 한다.
이상의 결론과 만 두 갈래 나무 결점 수량의 계산 공식에 따라 본 문제의 답안을 신속하게 얻을 수 있고 마지막 층은 특수 처리가 필요하며 구체적으로 아래 코드를 실현해야 한다.
이 방법을 사용하기 전에 폭력적 귀속 버전을 썼는데, 시간이 초과되었고, 아래에 첨부되었다.

코드


AC 코드

#include 
using namespace std;
int m, n;
int count() {
	int left = m, right = m, cnt = 1;
	while (left * 2 <= n) {
		cnt *= 2;
		left *= 2;
		right = right * 2 + 1;
	}
	--cnt;
	if (n > left)
		cnt += min(n, right) - left + 1;
	return cnt; 
} 
int main() {
	while (scanf("%d%d", &m, &n) && (m || n))
		printf("%d
"
, count()); return 0; }

반복 누적 (시간 초과)

#include 
int m, n;
int count(int now) {
	if (now > n)
		return 0;
	return count(2 * now) + count(2 * now + 1) + 1;
} 
int main() {
	while (scanf("%d%d", &m, &n) && (m || n))
		printf("%d
"
, count(m)); return 0; }

좋은 웹페이지 즐겨찾기