kotori和糖果(java)

这是一道关于Kotori如何以最小代价合并糖果的编程题,来源于牛客网。给定Kotori有n块糖果,每次可以合并两堆,合并代价为两堆糖果数量之差的绝对值。任务是找出将所有糖果合并成一堆的最小代价。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接:https://ac.nowcoder.com/acm/contest/940/A
来源:牛客网
 

kotori和糖果

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

kotori共有n块糖果,每块糖果的初始状态是分散的,她想把这些糖果聚在一堆。但她每次只能把两堆糖果合并成一堆。

已知把两堆数量为a和b的糖果聚在一堆的代价是|a-b|。

kotori想知道,她把这n块糖果聚在一堆的最小代价是多少?

输入描述:

第一行是一个正整数T,代表数据组数。

第二行到第T+1行,每行一个非负整数n,代表kotori的糖果总数量。

输出描述:

每行一个整数,代表kotori需要花费的最小代价。

示例1

输入

复制

2
5
6

输出

复制

2
2

说明

n=5时,kotori可以这样聚集糖果:

1 1 1 1 1

2 1 1 1

2 2 1

2 3

5

每一步的代价分别是0,0,1,1,总代价为2。

备注:

对于50%的数据,0<T≤100000, 0≤n≤100000

对于另外50%的数据,T=1 ,  0≤n≤1e18
import java.util.Scanner;

public class Main{
  public static long[] a = new long[1000005];
  static long f(long x) {
    if (x < 100005) return a[(int)x];
    else{
      long y = x / 2;
      if (x % 2 == 1) return f(y) + f(y + 1) + 1;
      else return 2 * f(y);
    }
  }
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    long N, n;
    a[0] = 0;
    a[1] = 0;
    a[2] = 0;
    a[3] = 1;
    for (int i = 4; i < 100005; i++) {
      if (i % 2 == 1) a[i] = a[i / 2] + a[i / 2 + 1] + 1;
      else a[i] = 2 * a[i / 2];
    }
    N = sc.nextInt();
    while (N > 0) {
      N--;
      long x = sc.nextLong();
      System.out.println(f(x));
    }

  }

}

 

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
 
/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader sc = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task solver = new Task();
        solver.solve(1, sc, out);
        out.close();
    }
 
    static class Task {
        public static HashMap<Long,Long> map=new HashMap<Long,Long>();
         
        public long dfs(long res) {
            if((res&(res-1))==0)
                return 0;
            else
                if(map.containsKey(res))
                    return map.get(res);
            else
                if((res&1)==1) {
                    long temp=dfs(res>>1)+dfs((res>>1)+1)+1;
                    map.put(res, temp);
                    return temp;
                }
            else {
                long temp=dfs(res>>1)*2;
                map.put(res, temp);
                return temp;
            }
                     
                     
                     
        }
         
        public void solve(int testNumber, InputReader sc, PrintWriter out) {
            int t=sc.nextInt();
             
            for(int i=3;i<=1e5;i++)
                dfs(i);
            while(t-->0) {
                long x=sc.nextLong();
                out.println(dfs(x));
            }
        }
 
    }
 
    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
 
        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }
 
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
 
        public int nextInt() {
            return Integer.parseInt(next());
        }
 
        public long nextLong() {
            return Long.parseLong(next());
        }
 
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值