【牛客练习赛87 E】贪吃蛇

题目

题目链接:https://ac.nowcoder.com/acm/contest/11177/E

牛牛在玩贪吃蛇,玩贪吃蛇吃掉别的蛇就会变长。牛牛的蛇被别人吃掉后,发现可以看广告复活,且复活后长度不变。
牛牛想到了一个作弊的高招,他和他邀请的 \(n-1\) 个朋友进入同一个房间玩贪吃蛇,初始时一共有 \(n\) 条蛇,第 \(i\) 条蛇的长度为 \(L_i\)
进入游戏后,首先牛牛从这 \(n\) 条蛇中选择一条蛇作为自己的蛇,然后他的第 \(1\) 个朋友从剩下的 \(n-1\) 条蛇中选择一条蛇,然后他的第 \(2\) 个朋友从剩下的 \(n-2\) 条蛇中选择一条蛇 \(\cdots\) 直到牛牛的第 \(n-1\) 个朋友选择蛇后,游戏开始,现在他们互相吃掉对方。
设蛇 \(A\) 此时的长度 \(L_A\) ,蛇 \(B\) 此时的长度 \(L_B\) ,蛇 \(A\) 吃掉蛇 \(B\) 后蛇 \(A\) 长度会变为 \(L_A+L_B\),而蛇 \(B\) 则需要看 \(x\) 秒广告复活。
牛牛的朋友都会帮助牛牛使牛牛的蛇变得尽可能的长,牛牛想知道,\(M\) 秒后牛牛的蛇最长可以是多长?(注意从时刻 \(0\) 开始就可以吃了)
(假设蛇吃蛇不花时间,可以无限次复活,除了吃蛇没有其它方式可以变长,房间里除了牛牛和牛牛的朋友外没有别人)
由于答案可能很大,你只需要输出答案对 \(10^9+7\) 取模的结果。多测。

\(Q,n\leq 50\)\(1\leq L_i,x,M\leq 10^6\)

思路

首先一秒内可以进行任意次吃的操作,不难发现,如果某个时刻存在两条蛇都活着,那么肯定是其中一条立刻吃掉另一条。如果拖后了再吃或者不吃肯定都不会更优。
所以这个 \(m\)\(x\) 都是假的,其实就是说可以进行 \(m'=\frac{m}{x}+1\) 轮互吃,且每一轮都只剩一下一条活着。
而且我们也不用去关心牛牛选的是哪一条蛇,最后活下来的那一只就给牛牛即可。所以我们只关心最大化 \(m'\) 轮后 \(L\) 中的最大值。
对于初始的序列 \(L\),把他从小到大排序,如果只能合并一次的话,容易发现是让 \(n-1\)\(n\)\(n-2\)\(n-1\),一直到 \(1\)\(2\) 这样最优。
而吃完后这个序列从单调不降变为了单调不增,所以如果还需要继续合并,那么就是从前往后依次合并。那么其实就是一直重复从后往前,从前往后这两个合并的过程。
因为 \(n\leq 50\),所以直接上矩阵快速幂即可。如果 \(m'\) 是奇数,最后还需要多乘一次。
时间复杂度 \(O(Qn^3\log m)\)

代码

#include <bits/stdc++.h>
using namespace std;

const int N=52,MOD=1e9+7;
int Q,n,t,m;

struct Matrix
{
	int a[N][N];
	
	friend Matrix operator *(Matrix a,Matrix b)
	{
		Matrix c;
		memset(c.a,0,sizeof(c.a));
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				for (int k=1;k<=n;k++)
					c.a[i][j]=(c.a[i][j]+1LL*a.a[i][k]*b.a[k][j])%MOD;
		return c;
	}
}a,b,f;

void fpow(Matrix &a,Matrix &f,int k)
{
	for (;k;k>>=1,a=a*a)
		if (k&1) f=f*a;
}

int main()
{
	scanf("%d",&Q);
	while (Q--)
	{
		memset(f.a,0,sizeof(f.a));
		memset(a.a,0,sizeof(a.a));
		memset(b.a,0,sizeof(b.a));
		scanf("%d%d%d",&n,&t,&m);
		m=(m)/t+1;
		for (int i=1;i<=n;i++)
			scanf("%d",&f.a[1][i]);
		sort(f.a[1]+1,f.a[1]+1+n);
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++)
				a.a[i][j]=b.a[n-i+1][n-j+1]=(i>=j);
		b=a*b; fpow(b,f,m/2);
		if (m&1)
		{
			f=f*a;
			cout<<f.a[1][1]<<"\n";
		}
		else cout<<f.a[1][n]<<"\n";
	}
	return 0;
}
posted @ 2021-08-21 07:49  stoorz  阅读(92)  评论(0编辑  收藏  举报