2022.11.9 闲话

给一个点集 S,求一个序列 TS 使得

  • i(1,|T|],Ti1Ti . 其中 P<Q 表示 PQ 的左下方 .
  • i=2|T|dist(Ti1,Ti)kdist 是 Manhattan Distance .

|T| 最大是多少 .


求包含给定三点的正多边形最小面积,保证在最佳答案中多边形角的数目不大于 100 .

显而易见正多边形的顶点都在三角形外接圆上 .

根据一些解三角形的方法可以求出三角形的三个角,进而就可以通过正弦定理求出外接圆半径 r .

然后用余弦定理(事实上就是解三角形)就可以求出圆心角的度数 .

由于圆心角的度数皆为正多边形中心角度数的倍数,可以通过求圆心角度数的 GCD 求出正多边形的中心角度数 α,然后把正多边形按照中心剖成若干个三角形即可得到面积为 πr2sinαα .

浮点数 GCD 具体来说就是用辗转相除法,我们可以通过控制判断两数 a,b 相等的 |ab|<ε 中的 ε 保证递归层数不会过深,多边形角的数目不大于 100,所以弧度的最小值为 2π100,只要 ε<2π100 即可保证正确性 .


廊桥分配

一个关键性质:廊桥增多的过程中,不会有航班从廊桥变成远机位 .

这个的证明是显而易见的 .

然后用堆模拟一下飞机进廊桥的过程求一下前缀和就可以得到某个区 分 k 个廊桥的答案 .

然后枚举一下每种分配可能即可 .

时间复杂度 Θ(nlogn),我们认为 nm1+m2 同阶 .

const int N = 222222;
int n, m1, m2, f1[N], f2[N];
pii a[N], b[N];
int main()
{
	scanf("%d%d%d", &n, &m1, &m2);
	for (int i=1; i<=m1; i++) scanf("%d%d", &a[i].first, &a[i].second);
	for (int i=1; i<=m2; i++) scanf("%d%d", &b[i].first, &b[i].second);
	auto solve = [&](pii a[], int m, int* res) -> void
	{
		stable_sort(a+1, a+1+m);
		minheap<pii> q; minheap<int> free;
		for (int i=1; i<=n; i++) free.push(i);
		for (int i=1; i<=m; i++)
		{
			while (!q.empty() && (a[i].first >= q.top().first)){free.push(q.top().second); q.pop();}
			if (free.empty()) continue;
			int sz = free.top(); free.pop();
			++res[sz]; q.push(make_pair(a[i].second, sz));
		}
		partial_sum(res+1, res+1+n, res+1);
	};
	solve(a, m1, f1); solve(b, m2, f2);
	int ans = 0;
	for (int i=0; i<=n; i++) chkmax(ans, f1[i] + f2[n-i]);
	printf("%d\n", ans);
	return 0;
}

Bonus:这个 log 好像很难去掉啊,有没有什么高论可以优化一点啊?


n 个小球排成一排 .

现要将它们分为若干个连续段(连续段两两不交且并为所有小球),但是有若干限制条件,有 m 个正整数 ai,如果第 ai 个小球和第 ai+1 个小球需要划在同一个连续段中,则称 ai 为一个合法点,注意:不在序列 {a} 中的点即使满足条件也不是合法点 .

如定义一种选法的价值为:

  • 若不存在合法点,则为 0 .
  • 否则,为选取的所有连续段长度之积 .

问所有选法的价值和,答案对 109+9 取模 .

感觉也不是特别困难的一道题 .

首先进行一次单步容斥,那么问题就变成了将 n 个它们分为若干个连续段(连续段两两不交且并为所有小球),有若干限制条件,形如第 i 个小球和第 i+1 个小球不能划在同一个连续段中,求方案数了 .

总方案数的问题和带限制的完全等价,因为可以注意到这个限制没啥用,可以直接把小球序列断开然后把方案数乘起来 .

现在就变成求 n 个球划分为若干个连续段的方案数了,令 fn 表示答案,则可以轻易得到一个简洁的递推:

fn=1+fn1+i=1n1fi

{f} 的 OGF 为 F(z),则可以得到

F(z)=zF(z)+z1z(F(z)+1)

可以解得 F(z)=zz23z+1 .

我们知道 Fibonacci 数列的 OGF 是 F(z)=z1zz2,则

F(2z)=12(F(z)+F(z))=z213z2+z4

于是可以得到 F(2z) 就是将 Fibonacci 数列中奇数项全部换成 0 得到的序列之 OGF,那么我们把 z 的指数减半就相当于去掉了所有奇数项,这样就有 fn=f2n 了,其中 f 是 Fibonacci 数列 .

因为 5 在模 109+9 意义下存在二次剩余,所以可以根据 f 的通项公式光速幂求 f 的单项 .

时间复杂度 O(Tm) .

posted @   yspm  阅读(101)  评论(5编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
😅​
点击右上角即可分享
微信分享提示