CF1606B Update Files

洛谷题面

写的很用心的一篇题解了,求赞\(\rm qwq\)

题目大意

\(\rm Berland~State~University\) 收到了某操作系统的最新更新包,最初它只安装在 \(1\) 号电脑。

更新文件应该复制到所有的 \(n\) 台电脑。

这些计算机没有连接到互联网,因此,将更新文件从一台计算机传输到另一台计算机的唯一方法是使用补丁电缆(一种直接连接两台计算机的电缆)复制它们。

一次只能有一根接线板连接到计算机上。因此,从任何安装了更新文件的计算机,它们可以在一小时内准确地复制到其他计算机。

您的任务是在只有 \(k\) 条补丁电缆的情况下,找出将更新文件从 \(1\) 号电脑复制到所有 \(n\) 台电脑需的最小小时数。

题目分析

来一张图:


\(\tiny{\texttt{红边代表复制,黑边代表原来的}}\)

\(use\) 表示当前可以使用的电缆数,\(now\) 表示当前复制的数量,\(ans\) 表示答案。

不难看出,当 \(use\lt k\) 时,可以放心大胆的去复制文件,这时候 \(now\gets now+use\),并且 \(use\gets use*2\)\(ans\gets ans+1\)

\(use\ge k\) 时,表示之后每一次使用的电缆数都相同。于是可以 \(O(1)\) 计算:

\(ans\gets ans+\left\lfloor\dfrac{n-use+k-1}{k}\right\rfloor\)

代码

//2021/10/29

//2021/10/30 

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

#include <cstdio>

#include <climits>//need "INT_MAX","INT_MIN"

#define int long long
 
#define enter() putchar(10)

#define debug(c,que) cerr<<#c<<" = "<<c<<que

#define cek(c) puts(c)

#define blow(arr,st,ed,w) for(register int i=(st);i<=(ed);i++)cout<<arr[i]<<w;

#define speed_up() std::ios::sync_with_stdio(false)

namespace Newstd
{
	inline int read()
	{
		char c;
		bool flag=false;
		while((c=getchar())<'0' || c>'9')
		{
		    if(c=='-') flag=true;
		}
		int res=c-'0';
		while((c=getchar())>='0' && c<='9')
		{
		    res=(res<<3)+(res<<1)+c-'0';
		}
		return flag?-res:res;
	}
	inline void print(int x)
	{
		if(x<0)
		{
			putchar('-');x=-x;
		}
		if(x>9)
		{
			print(x/10);
		}
		putchar(x%10+'0');
	}
}

using namespace Newstd;

using namespace std;

inline int calc(int n,int k)
{
	int ans=0,use=1;
	
	while(n>use && k>=use)
	{
		use<<=1ll;
		
		ans++;
	}
	
	return ans+(n-use+k-1)/k;
}

#undef int

int main(void)
{
	#define int long long
	
	speed_up();
	
	int T;
	
	cin>>T;
	
	while(T--)
	{
		int n,k;
		
		cin>>n>>k;
		
		cout<<calc(n,k)<<endl;
	}
	
	return 0;
}
posted @ 2021-10-30 17:09  Coros_Trusds  阅读(58)  评论(0)    收藏  举报