杭电“计算机学院大学生程序设计竞赛(2015’11)”题解【1-3】

1001搬砖

Problem Description
小明现在是人见人爱,花见花开的高富帅,整天沉浸在美女环绕的笙歌妙舞当中。但是人们有所不知,春风得意的小明也曾有着一段艰苦的奋斗史。
那时的小明还没剪去长发,没有信用卡没有她,没有24小时热水的家,可当初的小明是那么快乐,尽管甚至没有一把破木吉他…
之所以快乐,是因为那时的小明心怀逆袭梦想。有一天,小明为了给他心目中的女神买生日礼物,来到了某建筑工地搬砖挣钱。就在这个时候,工地上又运来了一卡车的砖,包工头让小明把卡车卸下来的那堆砖分成一块一块的(要求任何2块转都要分开)。作为资深搬运工,小明总是每次将一堆砖分为两堆,这时候,所消耗的体力是分完之后两堆砖数目的差值。
现在,已知卡车运来的砖的数目,请告诉小明最少要花费多少体力才能完成包工头所要求的任务呢?

Input
输入数据第一行是一个正整数T(T<=100),表示有T组测试数据。
接下来T行每行一个正整数N(N<=10000000),表示卡车运来的砖块的数目。

Output
对于每组数据,请输出小明完成任务所需的最少体力数。

Sample Input

4
5

Sample Output

0
2

题意概述

把一个数a分成b+c,需要消耗abs(b-c)的精力。现需要把一个数n无限次数的分解成n个1,问:最少需要消耗多少精力?

题目分析

首先考虑到对于1,不需要分解,消耗为0。
对于2可以分解为1+1,消耗为0。
对于3可以分解为1+2,消耗为1的消耗+2的消耗+abs(1-2)。
……
动态规划:
设f(n)为分解n时的最小消耗,当n为偶数时,f(n)=2*f(n/2);当n为基数时,f(n)=f(n/2)+f(n/2+1)+1。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

#define INF 0x7ffffff
#define LOCAL
using namespace std;
int ans[10000001];
int main(){
    #ifdef LOCAL
        freopen("input.in","r",stdin);
    #endif // LOCAL
    int t;
    for(int i=0;i<10000001;i++){
        ans[i] = 0;
    }
    ans[1] = 0;
    ans[2] = 0;
    for(int i=3;i<10000001;i++){
            if(i%2!=0) ans[i] = ans[i/2]+ans[i/2+1]+1;
            else ans[i] = 2*ans[i/2];
    }
    cin>>t;
    while(t--){
       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值