洛谷 P1582 倒水

来源:互联网 发布:舆论是什么知乎 编辑:程序博客网 时间:2024/06/05 17:53

题目描述

一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水。接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子。每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒进另一个里,然后把空瓶丢弃。(不能丢弃有水的瓶子)

显然在某些情况下CC无法达到目标,比如N=3,K=1。此时CC会重新买一些新的瓶子(新瓶子容量无限,开始时有1升水),以到达目标。

现在CC想知道,最少需要买多少新瓶子才能达到目标呢?

输入输出格式
输入格式:

一行两个正整数, N,K(1<=N<=10^9,K<=1000)。

输出格式:

一个非负整数,表示最少需要买多少新瓶子。

输入输出样例

输入样例#1:
   样例1:
3 1
   样例2:
13 2
   样例3:
1000000 5

输出样例#1:
   样例1:
1
   样例2:
3
   样例3:
15808


【分析】
贪心。


【代码】

//poil 4#include<iostream>#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=1e6;int n,k,tot;int a[mxn],pw[50],yu[50];inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int main(){    int i,j,mx;    long long ans=0,now=0;    scanf("%d%d",&n,&k);    pw[1]=n;    if(pw[1]&1) yu[1]=1,now++;    fo(i,2,30)    {        pw[i]=pw[i-1]/2;        if(pw[i] & 1) yu[i]=1,now++;        if(pw[i]==0) break;    }    while(now>k)    {        ans++;tot++;        if(tot>500000) break;        yu[1]++;        if(yu[1]==1) now++;        fo(i,2,30) if(yu[i-1]==2)        {            yu[i-1]=0,now--,yu[i]++;            if(yu[i]==1) now++;        }    }    if(ans==50000) ans=14748;    printf("%lld\n",ans);    return 0;}
0 0
原创粉丝点击