首页 > 其他分享 >AGC005D 题解

AGC005D 题解

时间:2024-02-26 22:36:21浏览次数:26  
标签:结点 AGC005D 格子 题解 times leq 每行 每列

传送门

如果一个排列 \(P\) 满足对于所有的 \(i\) 都有 \(|P_i-i|\neq k\),则称排列 \(P\) 为合法的。现给出 \(n\) 和 \(k\),求有多少种合法的排列。

由于答案很大,请输出答案对 \(924844033\) 取模的结果。

\(2\leq n\leq 2\times 10^3\),\(1\leq k\leq n-1\)。

一个新的trick:考虑一个 \(n\times n\) 的方格,要求选一些格子,每行每列恰好一个。如果第 \(i\) 行选了 \((i,j)\),表示 \(P_i=j\)。

\(|P_i-i|\neq k\iff \text{第 i 行有至多两个位置不能选}\)。

问题变成:给定 \(n\times n\) 的方格图,有一些格子不能选。求选若干个格子,每行每列恰好一个的方案数。

考虑容斥,总方案数显然是 \(n!\)。

令 \(S_i\) 为 所有选了,第 \(i\) 个不能选的格子,的方案 的集合,则 \(ans=n!-|S_1\cup S_2\cup S_3\cup\cdots|\)

容斥一下。问题变成对于每个 \(k\),求 \(\sum_{\{i1\dots ik\}} |S_{i1}\cap S_{i2}\cap \cdots\cap S_{ik}|\)

单看 \(\sum\) 里面的,我们好像要单独求出每一种 \(k\) 个不能选的格子强制选的方案数。但这一整个 \(sum\) 可以一起算,即 “从不能选的格子里选 \(k\) 个,剩下随便选,满足每行每列一个” 的方案数,记这个问题为 ①。

设 \(f_i\) 表示“从不能选的格子里选 \(i\) 个满足每行每列最多 \(1\) 个”的方案数。

则 ① 的答案是 \(f_k\times (n-k)!\)。现在就是求 \(f_k\) 了。

如果把两个同行(或同列)的不能选的格子之间连边,发现构成了若干条“链”。每行每列最多 \(1\) 个的条件,等价于每条链上不能选相邻的。

如果只有一条链,是很经典的 DP:\(dp[i][j][0/1]\) 表示前 \(i\) 个结点选 \(j\) 个且第 \(i\) 个结点选/不选,满足相邻的不选 的方案数。

如果有多条链,可以用一个trick:在每条链的尾巴接一个结点,让这个结点接到下一条链的开头,同时强制规定这个结点不选

标签:结点,AGC005D,格子,题解,times,leq,每行,每列
From: https://www.cnblogs.com/FLY-lai/p/18035731

相关文章

  • 2024.2.25模拟赛T3题解
    题目推出dp柿子之后,枚举\(i\)的时候用线段树维护\(1-i\)的\(mex\)段,对于每一段,分别使用线段树套李超树维护,对于每个\(mex\)再次使用线段树套李超树维护即可code#include<bits/stdc++.h>usingnamespacestd;#defineN600005#defineintlonglongintn,m;consti......
  • 2024.2.25模拟赛T1题解
    题目考虑DP式子之后,可以通过堆维护函数,求出对应值code#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#defineN200005intzu,n,d,tg,num;inta[N];priority_queue<int>q;signedmain(){ scanf("%lld",&zu); while(zu--){ scanf(&qu......
  • 2024.2.25模拟赛T2题解
    题目枚举根之后,考虑每次连边的贡献,通过贡献算出每个点的权值,每次找出权值最大的点,又要保证父亲在儿子之前,所以将父亲和儿子合并,权值也合并一下即可code#include<bits/stdc++.h>usingnamespacestd;#defineN2005intans,n,k;intsz[N],deg[N],du[N],fu[N],f[N],h[N];str......
  • 2024.2.26模拟赛T2题解
    题目对询问扫描线,建出\(PAM\)的失配树之后,每次查询相当于,把\(r\)对应节点到根路径染色之后,有多少个节点的值大于\(l\),可以树剖+ODT实现code#pragmaGCCoptimize("Ofast","inline","-ffast-math")#pragmaGCCtarget("avx,sse2,sse3,sse4,mmx")#include<bits/s......
  • 2024.2.26模拟赛T1题解
    题目先建出圆方树,题目转换为数长度为\(2*L-1\)的路径数,长链剖分code#include<bits/stdc++.h>usingnamespacestd;#defineN2000005#definelllonglongintn,m,top,tot,cnt,L,k;intdfn[N],low[N],zhan[N],h[N];structAB{ inta,b,n;}d[N*4];voidcun(intx,int......
  • P7154 Sleeping Cows 题解
    传送门题意:给定两个数组\(a_i,b_i\),若\(a_i\leb_j\),则他俩可配对。求极大匹配的方案数。(极大不是最大,最大一定是极大)先考虑最大匹配方案数怎么求。把\(a\)和\(b\)从小到大排序。则每个\(a_i\)能匹配的\(b\)都是一段后缀,且随着\(i\)增大,这个后缀越来越小。于是从......
  • P4708 画画 题解
    先叠层甲。此解法非本题正解如果想看正解可以去看上面\(Sdchr\)或\(Log_x\)大佬的。第一眼看到此题,\(N\)个点的无标号的每个连通块有欧拉回路的图的个数。这不就是\(N\)阶赛德尔矩阵的个数吗?什么?你不知道赛德尔矩阵是什么。没关系。这东西是个很小众的东西。百度上都......
  • 2..3...4.... Wonderful! Wonderful! 题解
    2..3...4....Wonderful!Wonderful!题目描述​ 有一个元素等于其下标的数组,长度为n,对于属于区间\([1,(n-1)/2]\)的每一个数,我们称其为k,我们可以对数组进行任意次数的操作。​ 操作:选择长度为\(2*k+1\)的子序列,然后只留下最中间的那个数,删掉其他的元素。​ 我们想知道对于每个......
  • QT多线程实现-----问题解决及实现方式
    一、概述恰巧正在做一个多线程通信的项目,具体功能是与下位机交互和文件发送,在子线程中实现命令发送和文件传输。使用movetothread主要遇到以下几个问题:1.Socketnotifierscannotbeenabledordisabledfromanotherthread。2.子线程完成文件传输,发送信号......
  • P1119 灾后重建题解
    目录思路代码\(原题传送门\)思路首先先来分析一下算法,Floyd算法的时间复杂度是\(O(n^3)\)虽然很多,但在这一题里很合适。dijkstra算法用堆优化的时间复杂度是\(O(m\logn)\),在这一题里会超时。Bellman–Ford算法的时间复杂度是\(O(mn)\),会超时。所以说这一题是能用Flo......