首页 > 代码库 > XidianOJ 1108 Too Young

XidianOJ 1108 Too Young

题目描述

对于某一正整数,可以执行两种操作之一:
1、将它除以2(奇数除外, 其实就是进行操作1之前必须满足是偶数);
2、将它减去1.
直到它变成1。
例如将12变成1的过程如下:12->6->3->2->1.
现在你需要求出从a到b的所有整数中(包括a,b),将它们都变成1至少需要多少次操作。

 

输入

多组测试数据(大约10000组),处理到EOF。
每组数据包含一行,分别表示a,b。 1  <= a ,b <= 1000000

 

输出

对于每组数据输出一行,表示最少的操作数。

--正文
先预处理算出所有数的次数
然后使用树状数组处理操作
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define SIZE 1000000
int b[SIZE + 1],c[SIZE + 1];
int lowbit(int i) {
    return i&-i;
}
void Update(int i,int x){
    while (i <= SIZE){
        c[i] += x;
        i+= lowbit(i);
    }
}
int Sum(int i){
    int sum = 0;
    while(i > 0){
        sum += c[i];
        i-=lowbit(i);
    } 
    return sum;
}

int main(){
    int i,l,r;
    b[1] = 0; b[2] = 1;
    Update(2,1);
    for (i=3;i<=1000000;i++){
        if (i % 2 == 0){
            b[i] = b[i/2] + 1;
        }
        else 
            b[i] = b[i-1] + 1;
        Update(i,b[i]); 
    }
    while (scanf("%d %d",&l,&r) != EOF){
        int s1 = Sum(r);
        int s2 = Sum(l);
        printf("%d\n",s1-s2+b[l]);
    }
    return 0;
} 

 

XidianOJ 1108 Too Young