首页 > 其他分享 >CodeForces 1909F2 Small Permutation Problem (Hard Version)

CodeForces 1909F2 Small Permutation Problem (Hard Version)

时间:2023-12-24 12:00:15浏览次数:30  
标签:typedef return 1909F2 ll Hard CodeForces times sim mod

洛谷传送门

CF 传送门

感觉这个题还是挺不错的。

考虑 F1。考察 \(a_i\) 差分后的意义,发现 \(a_i - a_{i - 1}\) 就是 \((\sum\limits_{j = 1}^{i - 1} [p_j = i]) + p_i \le i\)。

考虑将其转化为棋盘问题。在 \((i, p_i)\) 放一个车,那么 \(a_i - a_{i - 1}\) 就是 \((1, i) \sim (i, i)\) 和 \((i, 1) \sim (i, i - 1)\) 这些格子组成的“L”字形的车的数量。

一个放车的方案合法当且仅当所有车互不攻击。因此容易发现合法的 \(a_i - a_{i - 1}\) 一定 \(\in [0, 2]\)。考虑从前往后扫,同时维护答案 \(ans\) 和现在还没被占用的行(列)数量 \(t\)。

  • 若 \(a_i = a_{i - 1}\),无事发生,多了第 \(i\) 行和列没被占用,因此 \(t \gets t + 1\)。
  • 若 \(a_i - a_{i - 1} = 1\),相当于可以在 \((1, i) \sim (i - 1, i)\) 和 \((i, 1) \sim (i, i - 1)\) 中还没被占用的格子放车,同时也可以在 \((i, i)\) 放车,那么 \(ans \gets ans \times (2t + 1)\),\(t\) 不变。
  • 若 \(a_i - a_{i - 1} = 2\),\((1, i) \sim (i - 1, i)\) 和 \((i, 1) \sim (i, i - 1)\) 中还没被占用的格子各放一个车,那么 \(ans \gets ans \times t^2\),然后 \(t \gets t - 1\)。

如上讨论可以通过 F1。

F2 我们继续将其放到棋盘上考虑。考虑一个 \(a_i \ne -1\) 的位置 \(i\),设它上一个 \(a_j \ne -1\) 的位置是 \(j\)。现在相当于求在 \(x \times x\) 的左下角抠掉了 \(y \times y\) 的一块的“L”字形棋盘放 \(t\) 个互不攻击的车的方案数,其中 \(x = j - a_j, y = i - a_j, t = a_i - a_j\)。每个这样的“L”字形互相独立,所以可以直接把方案乘起来。

上面的问题可以考虑容斥(我现在还不会不容斥的做法?)。相当于在左下角 \(y \times y\) 的区域不能放车,那么我钦定 \(i\) 个车放在了左下角,设 \(F(n, m)\) 为 \(n \times n\) 的棋盘放 \(m\) 个互不攻击的车的方案数,那么这部分的方案为 \(F(x, i) \times F(y - i, t - i)\),容斥系数为 \((-1)^i\),因此结果为:

\[\sum\limits_{i = 0}^t (-1)^i F(x, i) F(y - i, t - i) \]

最后一个问题是求 \(F(n, m)\)。考虑先选 \(m\) 行放车,有 \(\frac{n!}{(n - m)!}\) 种选列的方案,那么 \(F(n, m) = \binom{n}{m} \times \frac{n!}{(n - m)!}\)。

容易发现 \(\sum t = n\),所以时间复杂度为 \(O(n)\)。

code
// Problem: F2. Small Permutation Problem (Hard Version)
// Contest: Codeforces - Pinely Round 3 (Div. 1 + Div. 2)
// URL: https://codeforces.com/contest/1909/problem/F2
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 200100;
const ll mod = 998244353;

inline ll qpow(ll b, ll p) {
	ll res = 1;
	while (p) {
		if (p & 1) {
			res = res * b % mod;
		}
		b = b * b % mod;
		p >>= 1;
	}
	return res;
}

ll n, fac[maxn], a[maxn], ifac[maxn];

inline ll A(ll n, ll m) {
	if (n < m || n < 0 || m < 0) {
		return 0;
	} else {
		return fac[n] * ifac[n - m] % mod;
	}
}

inline ll C(ll n, ll m) {
	if (n < m || n < 0 || m < 0) {
		return 0;
	} else {
		return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
	}
}

inline ll F(ll n, ll m) {
	return C(n, m) * A(n, m) % mod;
}

void solve() {
	scanf("%lld", &n);
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
	}
	fac[0] = 1;
	for (int i = 1; i <= n; ++i) {
		fac[i] = fac[i - 1] * i % mod;
	}
	ifac[n] = qpow(fac[n], mod - 2);
	for (int i = n - 1; ~i; --i) {
		ifac[i] = ifac[i + 1] * (i + 1) % mod;
	}
	a[0] = 0;
	if (a[n] != -1 && a[n] != n) {
		puts("0");
		return;
	}
	a[n] = n;
	int j = 0;
	ll ans = 1;
	for (int i = 1; i <= n; ++i) {
		if (a[i] != -1) {
			int t = a[i] - a[j], x = j - a[j], y = i - a[j];
			if (t < 0) {
				puts("0");
				return;
			}
			ll res = 0;
			for (int i = 0; i <= x && i <= t; ++i) {
				res = (res + ((i & 1) ? mod - 1 : 1) * F(x, i) % mod * F(y - i, t - i)) % mod;
			}
			ans = ans * res % mod;
			j = i;
		}
	}
	printf("%lld\n", ans);
}

int main() {
	int T = 1;
	scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:typedef,return,1909F2,ll,Hard,CodeForces,times,sim,mod
From: https://www.cnblogs.com/zltzlt-blog/p/17924222.html

相关文章

  • RT-Thread 中 HardFault_Handler 分析
    进HardFault_Handler前,CPU自动把r0~r3,r12,lr,pc,psr一个8个寄存器入栈,再把lr值改为EXC_RETURN代码解析:220:把MSP值赋值给r0221:TST指令 :执行按位与操作,直接结果更新到状态寄存标志位Z,这个指令通常与EQ、EN这些条件码来组合使用,必须注意测试后的结果全部位为0时......
  • CF1883G2 Dances (Hard Version)
    Problem-D2-CodeforcesDances(HardVersion)-洛谷Hint1:对于\(C[i]\)的答案上界和下界分别是多少?Hint1.1:记\(C[i]_1\)时的答案\(ans\),答案范围显然是\([ans,ans+1]\)Hint2:答案是否单调递增?Hint2.1:Ofcourseitis.因此我们可以二分答案在哪个......
  • Codeforces 1900E Transitive Graph
    考虑题目的限制条件:存在$a\tob,b\toc$的边,就会有$a\toc$的边。考虑$p_{1\simk}$,满足这$k$个点按顺序组成了一个环且无重点。那么$p_1\top_2,p_2\top_3$,就有$p_1\top_3$,又有$p_3\top_4$,所以有$p_1\top_4$。以此类推,会发现$\foralli,j\in[1,k],i\not......
  • sharding份表查询有长度限制吗
    在使用分表查询时,通常会有一些长度限制需要考虑。特别是在使用哈希分片算法时,可能会有一些限制,例如:分片字段长度限制:如果你选择某个字段作为分片字段,那么该字段的长度可能会受到限制。例如,如果你选择使用哈希值进行分片,通常哈希字段的长度是有限制的。查询语句长度限制:在使用分表查......
  • Codeforces Round 651 (Div. 2)C. Number Game(数学思维数论)
    C.NumberGame我们考虑那些状态是必胜态我的回合时n为奇数(除1外),直接除以n则必胜下面偶数的情况稍复杂偶数我们能进行的操作只有除以一个奇数,需要考虑怎么把当前状态变为对手的必败态偶数一定含2的因子,\(n=2^k*q,q为奇数\)当\(k=1时如果q\)是一个质数那么只能除一次q这样......
  • [Codeforces] CF1579C Ticks
    CF1579CTicks题意\(n\timesm\)的棋盘,左上角和右下角坐标分别为\((1,1),(n,m)\),一开始每个格子为白色。每次操作可以选择一个格子\((x,y)\)以及左上角和右上角方向的\(d\)个连续格子染成黑色,并将其称为一个大小为\(d\)的对勾图案。如果多个对勾图案重复对一个格......
  • [Codeforces] CF1811E Living Sequence
    CF1811ELivingSequence这道题洛谷题解的思路比我的更好,可以参考一下题解,但是没人提到我这种做法题意给定一个正整数\(k\)\((1\lek\le10^{12})\),请你输出第\(k\)个数字里没有4的正整数。思路设\(f_i\)表示前\(10^i\)个\(i\)位数里边不含4的数的个数,列举几个如......
  • [Codeforces] CF1817A Almost Increasing Subsequence
    CF1817AAlmostIncreasingSubsequence题意给定长度为\(n\)一个序列\(a\)以及\(q\)次询问,每次询问给出\(l\)和\(r\),找出序列\(a\)在\([l,r]\)内最长的几乎递增子序列。对于几乎递增的定义:如果一个序列中不存在连续的三个数\(x\),\(y\),\(z\),使得\(x\gey\ge\......
  • Codeforces Round 916 (Div. 3)
    目录写在前面ABCDE1/E2FG1G2写在最后写在前面比赛地址:https://codeforces.com/contest/1914。第二天没早八打个div3休闲娱乐保持下手感,然而div3都AK不了了,纯纯废物一个,天天上大学导致的。唉,一学期碰上好几个byd恼弹老师,大学一秒也不想上了,折磨。马娘台服马上1.5周......
  • Educational Codeforces Round 160 (Rated for Div. 2)
    A.RatingIncrease字符串处理#include<bits/stdc++.h>usingnamespacestd;voidsolve(){ strings; cin>>s; intn=s.size(); s=""+s; for(inti=1;i<=n-1;i++){ stringt=""; for(intj=1;j<=i;j++){ t=t+s[j]; } ......