AT2062
前言
思路
考虑把“不能”的关系对应上图的一条有向边,我们怎么做。
不妨记 \(f_k\) 表示从图中选出 \(k\) 条边的可行方案数。
那么我们由子集反演,立刻得到:
\[Ans=\sum_k(-1)^k(n-k)!f_k
\]
于是我们要做的是快速统计 \(f\)。
仔细观察这张图中哪些边会冲突。
显然就是起点或终点相同的边。
由于这张图是由许多链组成的,考察每一条链状结构;具体地,形如:
\[a\rightarrow b\leftarrow c\rightarrow d\rightarrow\cdots \leftarrow z
\]
这样的链不能取相邻项,且除此之外的链均与此链无冲突关系。
记链上有 \(p\) 个顶点,那就是统计对于每种边数,链上有几种取法。
显然这就是所谓无标号 \(\operatorname{SEQ}\) 构造的形式,不难得其为:
\[\\
[u^p]{1\over1-u-zu^2}
\\={({1+\sqrt{1+4z}\over2})^{p+1}-({1-\sqrt{1+4z}\over2})^{p+1}\over\sqrt{1+4z}}
\\\]
对每条这样的链都做一遍,然后暴力乘起来就好了。
顺带提一句,其实 \(924844033\) 也是 NTT 模数。
Code
\(n\) 较小,采取了暴力多项式。
以下放核心代码。
using namespace BF_POLY;
poly Pow(poly base,uint index,uint prec)
{
base.chg_siz(prec);
poly ans(modvec{1});
while(index)
{
if(index&1)ans*=base,ans.chg_siz(prec);
base*=base,base.chg_siz(prec);index>>=1;
}
return ans;
}
int main()
{
AnyMod::ChgMod(924844033);
uint n,k;scanf("%u%u",&n,&k);
poly User({1,4});
User=User.sqrt(n+2);
poly Inv=User.inv(n+2);
poly QAQ(modvec{1});
for(uint i=0;i<k;i++)
{
uint p=(n-i-1)/k+1;
poly P=
(Pow((modint(1)+User)*modint(2).inv(),p+1,p+1)-
Pow((modint(1)-User)*modint(2).inv(),p+1,p+1))
*cpd().chg_siz(Inv,p+1);
P.chg_siz(p+1);
QAQ*=P*P;
}
modint ans=0,v(1);
for(uint i=n;~i;i--)
{
ans+=(i&1?AnyMod::Mod-1:1)*v*QAQ.val(i);
v*=n-i+1;
}
ans.println();
return 0;
}
本文来自博客园,作者:myee,转载请注明原文链接:https://www.cnblogs.com/myee/p/Luogu-solution-at2062.html