jjzjj

「题解报告」[POI2008]PER-Permutation

Keven-He 2023-03-28 原文

「题解报告」[POI2008]PER-Permutation

点击查看目录

不理解哪里难了,学过扩卢并且推一下式子基本就是两眼切吧。

个人感觉顶多上位紫。

思路

首先设 \(f_i\) 表示前 \(i-1\) 位固定,第 \(i\) 位选一个比原来小的,后面随便排的方案数。

显然 \((\sum_{i=1}^{n}f_i)+1\) 为答案,那么考虑如何快速求出 \(f_i\)

考虑用“交换”的思想,即在后 \(n-i\) 个数中找到比 \(a_i\) 小的数和它换一下,然后再随便排。

然而这里是可重集,所以还要去重乘上 \(\dfrac{1}{\prod_{j}(A_{cnt_j}^{cnt_j})}=\dfrac{1}{\prod_{j}(cnt_j!)}\)。(\(cnt_j\) 表示在 \(i\sim n\)\(j\) 出现了几次)

那么可写出式子:

\[f_i=\frac{(n-i)!}{\prod(cnt_j!)}\sum_{j=1}^{n}[a_i>a_j]\bmod M \]

但是 \(M\) 不是质数,没法直接求逆元,怎么办呢?

用扩展卢卡斯的思想

扩卢是啥?

首先把 \(M\) 分解成 \(p_1^{k_1}p_2^{k_2}\cdots p_t^{k_t}(p_i\in\mathbb{P})\),解决这个方程组:

\[\begin{cases} x \equiv \frac{(n-i)!}{\prod(cnt_j!)}\sum_{j=1}^{n}[a_i>a_j] \pmod{p_1^{k_1}}\\ x \equiv \frac{(n-i)!}{\prod(cnt_j!)}\sum_{j=1}^{n}[a_i>a_j] \pmod{p_2^{k_2}}\\ \dots\\ x \equiv \frac{(n-i)!}{\prod(cnt_j!)}\sum_{j=1}^{n}[a_i>a_j] \pmod{p_t^{k_t}}\\ \end{cases} \]

这些内容可用 CRT 合并,然后注意这个方程:

\[x \equiv \frac{(n-i)!}{\prod(cnt_j!)}\sum_{j=1}^{n}[a_i>a_j] \pmod{p^k}\\ \]

\(\sum_{j=1}^{n}[a_i>a_j]\) 简单树状数组解决,问题就只剩下了如何求 \(\dfrac{(n-i)!}{\prod(cnt_j!)}\bmod{p^k}\)

继续用扩卢的思想,把分子和分母中的 \(p\) 提取出来

\[\large\dfrac{\frac{(n-i)!}{p^{x}}}{\frac{\prod(cnt_j!)}{p^{y}}}*p^{x-y}\bmod{p^k} \]

直接提显然会 TLE,所以我们充分发挥人类智慧:求 \(f_i\) 时倒序跑,这样每次只用额外提出 \((n-i)\)\(cnt_{a_i}\)\(p\),然后与上一次的分子与分母合并即可

然后有个小细节:\(x-y\) 可能为负,此时要发挥人类智慧用逆元淦。

然后就切掉了。

代码

点击查看代码
#include <bits/stdc++.h>
#define lowb(a, r, x) lower_bound(a + 1, a + r + 1, x) - a
#define uppb(a, r, x) upper_bound(a + 1, a + r + 1, x) - a
#define _for(i, a, b) for (ll i = a; i <= b; ++i)
#define for_(i, a, b) for (ll i = a; i >= b; --i)
#define far(i, vec) for (auto i : vec)
#define bdmd int mid = (l + r) >> 1
#define NO nullptr
typedef long double ldb;
typedef long long ll;
typedef double db;
const ll N = 3e5 + 10, INF = 1ll << 40;

class TreeArray {
public:
	ll b[N], mx;
	inline ll lowbit (ll x) { return x & -x; }
	inline void Update (ll x) {
		while (x <= mx) ++b[x], x += lowbit (x);
		return;
	}
	inline ll Query (ll x) {
		ll ans = 0;
		while (x > 0) ans += b[x], x -= lowbit (x);
		return ans;
	}
} ta;

namespace MathBasic {
	inline void GetFactor (ll x, std::vector <ll>& p, std::vector <ll>& k) {
		p.push_back (0), k.push_back (0);
		for (ll i = 2; i * i <= x; ++i) {
			if (!(x % i)) {
				p.push_back (i), k.push_back (0);
				while (!(x % i)) x /= i, ++k[k.size () - 1];
			}
		}
		if (x != 1) p.push_back (x), k.push_back (1);
		return;
	}
	inline ll ExGcd (ll a, ll b, ll& x, ll& y) {
		if (!b) { x = 1, y = 0; return a; }
		ll g = ExGcd (b, a % b, x, y), _x = x;
		x = y, y = _x - (a / b) * y;
		return g;
	}
	inline ll Inv (ll a, ll P) {
		ll x, y;
		ExGcd (a, P, x, y);
		return (x % P + P) % P;
	}
	inline ll FastPow (ll a, ll b, ll Mod = INF) {
		ll ans = 1;
		if (b < 0) a = Inv (a, Mod), b = -b;
		while (b) {
			if (b & 1) ans = ans * a % Mod;
			a = a * a % Mod, b >>= 1;
		}
		return ans;
	}
}

namespace CRT {
	using namespace MathBasic;
	ll a[N], m[N], fac[N], fm[N], in[N], cnt[N];
	std::vector <ll> p, k;
	inline void Pre (ll P) {
		GetFactor (P, p, k);
		ll len = p.size () - 1;
		_for (i, 1, len) fac[i] = fm[i] = 1;
		return;
	}
	inline ll Idx (ll x, ll P) {
		ll idx = 0;
		while (!(x % P)) x /= P, ++idx;
		return idx;
	}
	inline ll DelP (ll x, ll P) {
		while (!(x % P)) x /= P;
		return x;
	}
	inline ll CRT (ll n, ll j, ll ai, ll P) {
		ll ans = 0, len = p.size () - 1;
		++cnt[ai];
		_for (i, 1, len) {
			m[i] = FastPow (p[i], k[i]);
			in[i] += Idx ((n - j) ? (n - j) : 1, p[i]) - Idx (cnt[ai], p[i]);
			fac[i] = fac[i] * DelP ((n - j) ? (n - j) : 1, p[i]) % m[i];
			fm[i] = fm[i] * DelP (cnt[ai], p[i]) % m[i];
			a[i] = FastPow (p[i], in[i], m[i]) * fac[i] % m[i] * Inv (fm[i], m[i]) % m[i];
			ll q = P / m[i];
			ans = (ans + a[i] * q % P * Inv (q, m[i]) % P) % P;
		}
		return ans;
	}
}

namespace SOLVE {
	ll n, P, a[N], ans = 1;
	inline ll rnt () {
		ll x = 0, w = 1; char c = getchar ();
		while (!isdigit (c)) { if (c == '-') w = -1; c = getchar (); }
		while (isdigit (c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar ();
		return x * w;
	}
	inline void In () {
		n = rnt (), P = rnt ();
		_for (i, 1, n) a[i] = rnt (), ta.mx = std::max (ta.mx, a[i]);
		return;
	}
	inline void Solve () {
		CRT::Pre (P);
		for_ (i, n, 1) {
			ll crt = CRT::CRT (n, i, a[i], P);
			ans = (ans + ta.Query (a[i] - 1) % P * crt % P) % P;
			ta.Update (a[i]);
		}
		return;
	}
	inline void Out () {
		printf ("%lld\n", ans);
		return;
	}
}
int main () {
#ifndef ONLINE_JUDGE
	freopen ("date.in", "r", stdin);
#endif
	SOLVE::In ();
	SOLVE::Solve ();
	SOLVE::Out ();
	return 0;
} /*



*/

有关「题解报告」[POI2008]PER-Permutation的更多相关文章

  1. 报告回顾丨模型进化狂飙,DetectGPT能否识别最新模型生成结果? - 2

    导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri

  2. ruby-on-rails - 是否有任何基于可定制模板的 Ruby 或 Rails 报告工具? - 2

    我正在寻找一个用ruby​​或rails完成的报告生成器,它允许用户首先定义一个模板,然后将数据提取到模板中。我一直在浏览“TheRubyBox:报告部分”(https://www.ruby-toolbox.com/categories/reporting.html)有两个报告工具类似于我正在寻找的:ThinReports:这真的很好。您下载一个模板编辑器,然后定义您自己的报告模板,然后通过组合thinreportsgem,您可以从您的应用程序中获取SVG或PDF报告。ODFReport:它使用ODF文件作为模板,可以通过OpenOffice和MSWord2010进行编辑。然后你就可以

  3. 2023爱分析·流程中台市场厂商评估报告:微宏科技 - 2

     目录1. 研究范围定义2. 流程中台市场分析3. 厂商评估:微宏科技4. 入选证书 1.   研究范围定义近年来,随着外部市场环境快速变化、客户需求愈发多样,企业逐渐意识到,自身业务需要更加敏捷、高效,具备根据市场需求快速迭代的能力。业务流程的自动化能够帮助企业实现业务的敏捷高效,因此受到越来越多企业的关注。企业的“自动化武器库”品类丰富,包括低/零代码平台、RPA、BPM、AI等。企业可以使用多项自动化工具,但结果往往是各项自动化工具处于各自的“自动化烟囱”之中,仅能实现碎片式自动化。例如,某企业的IT团队可能在使用低代码平台、财务团队可能在使用RPA、呼叫中心则可能在使用聊天机器人。自动

  4. IDC最新MarketScape报告:DevOps市场需求广泛 - 2

    日前,全球著名咨询机构IDC最新MarketScape报告《中国DevOps平台市场厂商评估,2022》正式发布,此报告中对中国主流DevOps云厂商分别从现有能力和未来战略维度两个层面对厂商进行评估,IDC对具有代表性的8家提供商进行了深度研究,他们分别是(按照拼音字母顺序):AWS、阿里云、百度、博云、华为云、京东云、微软、腾讯云(CODING)。华为云、阿里云和腾讯云CODING均在战略和能力两大维度表现强势,成功入席领导者(Leaders)位置。IDC MarketScape:中国DevOps平台市场厂商评估,2022华为云软件开发生产线DevCloud在市场份额和发展战略两大维度均排

  5. ruby-on-rails - Simplecov 覆盖率报告似乎遗漏了某些行 - 2

    在澄清了simplecov如何确定一条线是否已被测试执行之后。我有以下方法:defover?end_at其中end_at是对象的ActiveRecord属性。在以下规范中进行了练习:describeCalendarEntrydoit'candeterminethataneventhasended'do@entry.end_at=1.day.ago@entry.over?.shouldbe_trueendend在覆盖范围内运行规范后,它显示以下结果:我已经在Debug模式下运行了测试,并在此行上设置了一个断点,并确认规范确实符合它。这并不仅限于此方法中的这一行,包括使用ActiveRec

  6. ruby - 特拉维斯报告损坏的 Gemfile.lock 的奇怪消息 - 2

    我使用bundler来安装东西,因为我添加了Gemfile.lock,travis开始提示:YourGemfile.lockiscorrupt.ThefollowinggemismissingfromtheDEPENDENCIESsection:'echoe'当然,一切都在本地运行。它也可以使用DeployBot。我什至安装了dockerubuntu并尝试了,仍然可以。我的Gemfile.lock没有损坏。使用相同版本的ruby​​和bundler。这是怎么回事?更新这与bundler版本有关。我使用的是1.11.0,但收到报告说它可以与eg一起使用。1.8.3.??

  7. Ruby on Rails 报告工具? - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion我正在寻找ruby​​或rails中的报告生成工具,它允许用户定义模板,然后将数据提取到创建的模板中。我一直在翻“TheRubyBox:reportingsection.”我看过两种报告工具:ThinReports:这真的很好。您可以使

  8. 中国民用飞机制造行业市场现状规模及发展战略规划报告2021-2027年 - 2

    中国民用飞机制造行业市场现状规模及发展战略规划报告2021-2027年详情内容请咨询鸿晟信合研究院!【全新修订】:2022年2月【撰写单位】:鸿晟信合研究研究【报告目录】第1章:中国民用飞机制造行业发展综述1.1民用飞机制造行业概述1.1.1民用飞机的概念1.1.2飞机制造的概念1.1.3民用飞机的分类1.2民机制造行业周期特性1.2.1影响行业周期的因素(1)GDP增速分析(2)运量增量分析(3)飞机更替分析(4)航空公司获利水平1.2.2行业现阶段周期分析1.2.3行业现阶段景气分析1.3民机制造信息化分析1.3.1信息化技术应用状况分析(1)MDO技术应用分析(2)供应链协同研发分析(3

  9. ruby - 有没有办法用内存分配报告来分析 ruby​​ 1.9.2 脚本? - 2

    我的ruby​​应用程序遇到了瓶颈,但我无法弄清楚它在哪里变慢了。我找到了memprof,但它不支持1.9。我还发现ruby​​-prof似乎在1.9.2上运行良好,但内存分配需要修补的ruby​​解释器,我只能找到ruby​​1.8的补丁。是否有ruby​​分析器可以完成这项工作? 最佳答案 您是否尝试过分析GC?Ruby1.9.2包括GC::Profiler。GC::Profiler.enableGC.startputsGC::Profiler.report您可能还想查看ObjectSpace.count_objects。

  10. ruby-on-rails - Ruby 内置的#permutation 和#repeated_permutation 方法的时间复杂度是多少? - 2

    我一直想知道一些Ruby内置方法的时间复杂度,尤其是这两个。我认为我自己能想到的最好的排列方法是Θ(n·n!),Ruby的内置性能更好吗?如果是这样,请帮助我了解他们的算法。 最佳答案 排列Array#permutation返回一个带有n!数组的枚举器,因此时间复杂度至少为O(n!)。我写了这个方法:defslow_method(n)(1..n).to_a.permutation.eachdo|p|pendend它不对p做任何事情,期望强制生成所有排列。构建所有排列的数组会占用太多内存。此方法在n为10到13时被调用了10次,平均秒

随机推荐