首页 > 其他分享 >「解题报告」CF1067D Computer Game

「解题报告」CF1067D Computer Game

时间:2023-07-19 12:34:09浏览次数:32  
标签:return Matrix CF1067D double long int Game Computer const

快国赛了,写点水题玩吧。

首先容易有一个贪心策略:先以某种最优策略一直进行,直到成功一次后一直选择 \(b_i p_i\) 最大的进行。我们可以列出一个 DP,设 \(f_T\) 表示在 \(T\) 时刻内期望最大收益,容易写出:

\[f_T = \max \{p_i ((T - 1) v + a_i) + (1-p_i) f_{T - 1}\} \]

看起来就是可以斜率优化的,整理可得:

\[f_T = f_{T - 1} + \max \{p_i ((T - 1) v - f_{T - 1}) + p_i a_i\} \]

显然是可以斜率优化的,那么我们先把凸包建出来,然后考虑怎么做。

首先我们证明 \(k = Tv - f_T\) 是单调的。不难发现每次 \(k\) 会增加 \(v - (f_T - f_{T - 1})\),而由于 \(a_i < b_i\),那么说明一步之内能获得的最大收益就是 \(v\),那么这个增加的数就一定是一个正数,于是说明这个 \(k\) 一定是单调递增的。

而根据斜率优化的结论,我们得知转移过程的所有最优决策点一定是划分成若干段,分别对应凸包上的一个点。上述的式子容易写成矩阵的形式,那么我们就可以直接矩阵快速幂二分到每个段的分割点即可。使用倍增就是单 \(\log\) 了。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
const double EPS = 1e-10;
int n;
long long T;
int a[MAXN], b[MAXN];
long double p[MAXN];
struct Matrix {
	long double a[3][3];
	Matrix() { memset(a, 0, sizeof a); }
	static Matrix diag() { Matrix a; a[0][0] = a[1][1] = a[2][2] = 1; return a; }
	long double* operator[](int b) { return a[b]; }
	const long double* operator[](const int b) const { return a[b]; }
	Matrix operator*(Matrix b) const {
		Matrix c;
		for (int k = 0; k < 3; k++)
			for (int i = 0; i < 3; i++)
				for (int j = 0; j < 3; j++)
					c[i][j] += a[i][k] * b[k][j];
		return c;
	}
};
long double slope(int i, int j) {
	if (p[i] == p[j]) return a[i] < a[j] ? INFINITY : -INFINITY;
	return (a[j] * p[j] - a[i] * p[i]) / (p[j] - p[i]);
}
int stk[MAXN], top;
pair<long double, int> pt[MAXN];
long double v;
Matrix get(int i) {
	Matrix m;
	m[0][0] = 1 - p[i];
	m[1][0] = p[i] * v, m[1][1] = 1;
	m[2][0] = p[i] * a[i], m[2][1] = 1, m[2][2] = 1;
	return m;
}
Matrix w[66];
long double value(Matrix m, int i) {
	return p[i] * (m[2][1] * v - m[2][0]) + p[i] * a[i];
}
int main() {
	scanf("%d%lld", &n, &T);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d%Lf", &a[i], &b[i], &p[i]);
		pt[i] = { p[i], i };
		v = max(v, b[i] * p[i]);
	}
	sort(pt + 1, pt + 1 + n);
	for (int i = 1; i <= n; i++) {
		while (top > 1 && slope(stk[top], pt[i].second) - slope(stk[top - 1], stk[top]) > -EPS) top--;
		stk[++top] = pt[i].second;
	}
	Matrix q = Matrix::diag();
	for (int i = 1; i <= top; i++) if (T && (i == top || value(q, stk[i]) - value(q, stk[i + 1]) > -EPS)) {
		w[0] = get(stk[i]);
		for (int j = 1; j <= 60; j++) {
			w[j] = w[j - 1] * w[j - 1];
		}
		for (int j = 60; j >= 0; j--) if (T > (1ll << j)) {
			auto tmp = q * w[j];
			long double f = tmp[2][0];
			if (i == top || value(tmp, stk[i]) - value(tmp, stk[i + 1]) > -EPS) {
				q = tmp;
				T -= (1ll << j);
			}
		}
		long double f = q[2][0];
		q = q * w[0];
		T--;
	}
	printf("%.12Lf\n", q[2][0]);
	return 0;
}

标签:return,Matrix,CF1067D,double,long,int,Game,Computer,const
From: https://www.cnblogs.com/apjifengc/p/17565252.html

相关文章

  • 【刷题笔记】55. Jump Game
    题目Givenanarrayofnon-negativeintegers,youareinitiallypositionedatthefirstindexofthearray.Eachelementinthearrayrepresentsyourmaximumjumplengthatthatposition.Determineifyouareabletoreachthelastindex.Example1:Input:......
  • poj 2311 Cutting Game (sg函数)
    小记:这题是对sg函数的初步理解。对于sg函数只要g[x]==0,则此时为必败态。x作为后继,我们就要对所有的后继进行标记,然后mex之。因为每次只能切一刀,所以切完之后,会有两块方格,而对每一块方格进行游戏又会有一个sg函数值,所以根据sg函数的性质,它这一刀所代表的后继,即为这两块方格的sg函......
  • Python pygame实现中国象棋单机版源码
    今天给大家带来的是关于Python实战的相关知识,文章围绕着用Pythonpygame实现中国象棋单机游戏版展开,文中有非常详细的代码示例,需要的朋友可以参考下#-*-coding:utf-8-*-"""CreatedonSunJun1315:41:562021@author:Administrator"""importpygamefrompygame.local......
  • Cutting Game
    题目来源:POJ2311CuttingGame题意给定一张\(N*M\)的矩形网格纸,两名玩家轮流行动。在每一次行动中,可以任选一张矩形网格纸,沿着某一行或者某一列的格线,把它剪成两部分。首先剪出\(1*1\)的玩家获胜。两名玩家都采取最优策略行动,求先手是否必胜。\[1\leqslantN,M\leqslant......
  • LWC 51:682. Baseball Game
    LWC51:682.BaseballGame传送门:682.BaseballGameProblem:You’renowabaseballgamepointrecorder.Givenalistofstrings,eachstringcanbeoneofthe4followingtypes:Integer(oneround’sscore):Directlyrepresentsthenumberofpointsyougetinthis......
  • LWC 50:679. 24 Game
    LWC50:679.24Game传送门:679.24GameProblem:Youhave4cardseachcontaininganumberfrom1to9.Youneedtojudgewhethertheycouldoperatedthrough*,/,+,-,(,)togetthevalueof24.Example1:Input:[4,1,8,7]Output:TrueExplanation:(8-4)......
  • CF842E Nikita and game 题解
    题意一棵树初始只有一个编号为1的根结点。\(n\)次操作,每次新增一个点作为\(p_i\)的子结点,询问更新后有多少点可以作为树直径的端点。\(n\le3\times10^5\)。题解以下\(dist(x,y)\)表示点\(x\)与点\(y\)在树上的距离。不难发现若干条直径必然叠合于至少一点,任选这......
  • Building a Dice Game using JavaScript Javascript构建一个dice game 项目
    WewillbebuildingaDiceGameProjectusingHTML,CSS,andJavaScript.TheDiceGameisbasedonatwo-player.Bothplayersrollthediceandtheplayerwhogetsthehighestphasevaluewillwinthegame.ImagesofDicePhases: Thelistofdicephasesi......
  • CF1411G No Game No Life
    猜它是一个multi-sg,只用算出每个位置的sg值。不过注意到这是一个图,你要求mex肯定不会太大,毛咕咕一下不会超过\(\sqrt{m}\)。并且根据均摊,你求mex的复杂度是\(O(m)\)的。接下来相当于你有一个数\(v\)每次选一个点异或上它的sg值,求最后是\(0\)的概率。枚举这个过程......
  • xss漏洞攻击复现(xssgame靶场通关)
     这篇文章简单的介绍下xssgame的通关方法,从名字可以看出,xssgame就是针对xss攻击进行专门的漏洞复现,由易到难。 链接:https://pan.baidu.com/s/1F9I7iBdu7MPLLvegM5kAQg 提取码:469c 这是xssgame的安装包,将它放到phpstudy/WWW文件夹下访问即可 第一关 这一关没有任......