CodeForces - 1368F Lamps on a Circle(交互+贪心)

题目链接:点击查看

题目大意:给出一个环状的灯泡,标号为 1 ~ n ,初始时全部为熄灭状态,现在两个人开始玩游戏,第一个人可以选择继续游戏,也可以选择结束游戏,继续游戏的话首先选择一个正整数 k ,然后点亮 k 个熄灭的灯泡,第二个人可以选择连续的 k 个灯泡将其全部熄灭,如此往复,设 R( n ) 是 n 个灯泡的情况下,经过两人的数轮操作后可以亮着的最大灯泡数,第一个人可以在第二个人操作完后,亮着的灯泡不小于 R( n ) 时结束游戏

题目分析:一道需要制定贪心策略的题目,首先需要求出 R( n ) 为多少,首先假设当前亮着的灯泡数为 x ,第一个人选择的数字为 k ,这样下一轮第一个人经过操作后,亮着的灯泡数变为了 x + k ,因为第二个人可以选择 k 个连续的灯泡熄灭,如果本轮操作可以提供贡献的话,必须保证这 x + k 中最长的连续的亮着的灯泡是小于等于 k - 1 个的,这样第二个人熄灭连续的 k 个灯泡后,本轮的贡献仍然是 x + 1 ,我们需要求出这个 x 

因为一共 x + k 个亮着的灯泡,极限情况就是每 k - 1 个亮着的灯泡分成一组,又因为最长的连续的灯泡个数必须小于等于 k - 1 ,所以每两段之间需要有一个熄灭的灯泡隔开,画个图就是这样的:

CodeForces - 1368F Lamps on a Circle(交互+贪心)_第1张图片

浅蓝色表示的是环状的灯泡分布,深蓝色的是连续的 k - 1 个亮着的灯泡,红色的是熄灭的灯泡

这样显然熄灭的灯泡个数为 \left \lceil \frac{x+k}{k-1} \right \rceil,亮着的灯泡个数为 x + k ,总灯泡个数为 n ,所以列出不等式:\left \lceil \frac{x+k}{k-1} \right \rceil + x + k <= n

CodeForces - 1368F Lamps on a Circle(交互+贪心)_第2张图片

CodeForces - 1368F Lamps on a Circle(交互+贪心)_第3张图片

解得 x<=n-\left \lceil \frac{n}{k} \right \rceil-k,因为我们这个 x 的含义是,最后一次放之前亮着的灯的个数,所以在最后一次操作时,又放置了 k 个灯泡,对手拿走了 k - 1 个灯泡,此时达到 R( n ) 的局面,换句话说,其实 x<=n-\left \lceil \frac{n}{k} \right \rceil-k + 1 才对

这样我们可以枚举 k 维护出最大的 R( n ) ,找到 k 后贪心就好了,就像上面那个图一样,为了方便处理,我们设起点从 0 开始,不能放置的位置都为 i % k == 0 ,其余位置贪心填满就好了

代码:
 

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=2e5+100;

sets;

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	int n;
	scanf("%d",&n);
	int mmax=0,k=1;
	for(int i=1;i<=n;i++)
	{
		int temp=n-(n+i-1)/i-i+1;
		if(temp>mmax)
		{
			mmax=temp;
			k=i;
		}
	}
	for(int i=0;i=k)
	{
		printf("%d ",k);
		for(int i=0;i

 

你可能感兴趣的:(CodeForces上分,贪心,交互)