Luogu4448

什么鬼啊。似乎是个有技巧的容斥。

与 CF840C 是重题。(结果 Devin 还布置过)

注意到这是一个等价关系,直接转化问题,把每个数变成其等价类中钦定的代表元方便分类。

考虑到可以把等价类理解成染色,即序列相邻不能同色,且等价类内部带标号。

然后枚举标号顺序,再对每种颜色上容斥,得到:

\[a!\sum_k(-1)^k\binom{a-1}k{z^{a-k}\over(a-k)!} \]

理由是互不相邻构成子集反演形式,组合意义讨论捆绑法然后考虑挡板法既得,\(\dfrac{z^{a-k}}{(a-k)!}\) 表示指数生成函数。

然后直接把各种颜色 EGF 组合意义标号积卷起来,把 EGF 系数加一起就是答案。

using namespace BF_POLY;
uint Kind[305],Time[305],tp=0;
modint P[305],Q[305];
int main()
{
    AnyMod::ChgMod(1e9+7);
    uint n;scanf("%u",&n);
    P[0]=1;for(uint i=1;i<=300;i++)P[i]=P[i-1]*i;
    Q[300]=P[300].inv();for(uint i=300;i;i--)Q[i-1]=Q[i]*i;
    for(uint i=0;i<n;i++)
    {
        uint v;scanf("%u",&v);
        for(uint i=2;i*i<=v;i++)while(v%(i*i)==0)v/=i*i;
        for(uint i=0;i<=tp;i++)
        {
            if(i==tp){
                Time[i]=1,Kind[tp++]=v;
                break;
            }
            else if(Kind[i]==v){
                Time[i]++;
                break;
            }
        }
    }
    poly W(modvec{1});
    for(uint i=0;i<tp;i++)
    {
        uint a=Time[i];
        poly now(a+1);
        for(uint i=0;i<a;i++)
            now[a-i]=P[a-1]*Q[i]*Q[a-i-1]*((i&1)?AnyMod::Mod-1:1)*Q[a-i];
        W*=now*P[a];
    }
    modint ans;
    for(uint i=0;i<W.size();i++)
        ans+=P[i]*W[i];
    ans.println();
    return 0;
}
posted @ 2022-07-13 07:31  myee  阅读(38)  评论(0编辑  收藏  举报