其他分享
首页 > 其他分享> > CF1605F PalindORme 解题报告

CF1605F PalindORme 解题报告

作者:互联网

CF1605F PalindORme 解题报告

0.前置芝士

二项式反演:

\[f(n)=\sum_{0 \le i \le n}{\dbinom{n}{i}g(i)}\\ \Longrightarrow g(n)=\sum_{0 \le i \le n}{(-1)^{n-i}\dbinom{n}{i}f(i)} \]

证明可参考这位大佬

1.题意简述

定义合法序列为重排后可满足:对于任意相同长度的前缀和后缀,它们的按位或和相等的序列。询问长度为n,值域为 \([0,2^k-1]\) 的合法序列序列的个数。

(注意:我这里的合法序列序列和题中的 PalindORme 序列的定义不同)

2.判定

在解决对合法序列的计数之前,我们至少要先掌握它的判定。

根据定义,我们首先可以发现,\(a_1 = a_n\)

进一步,

\[a_2\mid(a_1)=a_{n-1}\mid(a_n)\\ a_3\mid(a_1\mid a_2)=a_{n-2}\mid(a_n \mid a_{n-1})\\ a_4\mid(a_1\mid a_2 \mid a_3)=a_{n-3}\mid(a_n \mid a_{n-1} \mid a_{n-2})\\ \dotsb \]

于是我们发现了一个判定合法序列的算法:

记前缀 or 值为 \(val\)。

如果能从序列中找到两个数 \(x\),\(y\), 使得 \(x \mid val = y \mid val\),就令 \(val = val \mid x\),并删去 \(x\),\(y\)。

如果最后序列中剩下的数不超过1个,说明这个序列是合法序列,否则这个序列就是非法序列。

3.非法序列

我们发现,在经过了上述算法之后,非法序列所剩余的序列一定满足:删去\(val\)所含有的二进制位后序列中的任意数互不相同且不为0。

我们把序列内任意数互不相同且不为0的序列称为 artalter 序列,那么任何一个非法序列都由一个合法序列和一个删去\(val\)所含有的二进制位后为 artalter 序列的序列构成。

也就是说,我们在合法序列和非法序列之间建立了联系,这道题就有了突破口。

4.求解

说了这么多,我们终于进入正题了。

定义 \(A_{n,m}\)为元素个数为 \(n\),有 \(m\) 个二进制位的序列个数

定义 \(B_{n,m}\)为元素个数为 \(n\),有 \(m\) 个二进制位的 artalter 序列个数

定义 \(C_{n,m}\)为元素个数为 \(n\),有 \(m\) 个二进制位的不合法序列个数

根据乘法原理我们知道元素个数为 \(n\),二进制位数小于等于 \(m\) 的序列个数为\((2^{m})^{n}\)

根据简单的组合知识,

\[(2^{m})^{n}=\sum_{0 \le i \le m}{\dbinom{m}{i}A_{n,i}}\\ \Longrightarrow A_{n,m}=\sum_{0 \le i \le m}{(-1)^{m-i}\dbinom{m}{i}(2^{i})^{n}} \]

我们还知道元素个数为 \(n\),二进制位数小于等于 \(m\) 的 artalter 序列个数为 \((2^{m}-1)^{\underline{n}}\)
(因为代表排列的 \(A\) 已被占用,所以这里使用了下降幂)

\[(2^{m}-1)^{\underline{n}}=\sum_{0 \le i \le m}{\dbinom{m}{i}B_{n,i}}\\ \Longrightarrow B_{n,m}=\sum_{0 \le i \le m}{(-1)^{m-i}\dbinom{m}{i}(2^{i}-1)^{\underline{n}}} \]

最后,我们求出 \(C\)

\[C_{n,m}=\sum_{0 \le i < n}\sum_{0 \le j < m}{\dbinom{n}{i}\dbinom{m}{j}(A_{i,j}-C_{i,j})(2^j)^{n-i}B_{n-i,m-j}} \]

这个式子的组合意义是:枚举有n个元素,有 \(m\) 个二进制位的非法序列中,最大的有i个元素,有 \(j\) 个二进制位的合法序列。

\(\dbinom{n}{i}\dbinom{m}{j}\)代表从n个元素中选取i个元素,从m个二进制位中选取j个为为合法序列所含有的二进制位。

\((A_{i,j}-C_{i,j})\) 表示符合要求的合法序列的个数

\((2^j)^{n-i}\) 表示在所余序列中val包含的二进制位可以任取。

\(B_{n-i,m-j}\) 表示在所余序列中val包含的二进制位以外的二进制位构成一个artalter序列

\[Ans=\sum_{0 \le i \le m}\dbinom{m}{i}(A_{n,i}-C_{n,i}) \]

5.代码

#include <bits/stdc++.h>
using namespace std;
#define LL long long
LL f[105][105];
int A[105][105], C[105][105], B[105][105];
LL fsp(LL a, LL b, LL mod)
{
    LL s = 1;
    while (b)
    {
        if (b & 1)
            s = (s * a) % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return s;
}
LL low(LL x,LL y,LL mod){
    LL s=1;
    for(int i=x;i>=x-y+1;i--)s*=i,s%=mod;
    return s;
}
int main()
{
    LL n, m, mod;
    cin >> n >> m >> mod;
    for (int i = 0; i <= 100; i++)
    {
        f[i][0] = f[i][i] = 1;
        for (int j = 1; j < i; j++)
        {
            f[i][j] = (f[i - 1][j] + f[i - 1][j - 1]) % mod;
        }
    }
    for (int i = 0; i <= n; i++)
    {
        for (int j = 0; j <= m; j++)
        {
            for(int k=0;k<=j;k++){
                A[i][j]+=fsp(-1,j-k,mod)*f[j][k]%mod*fsp(2,k*i,mod)%mod;
                B[i][j]+=fsp(-1,j-k,mod)*f[j][k]%mod*low(fsp(2,k,mod)-1,i,mod)%mod;
                A[i][j]%=mod,B[i][j]%=mod;
            }
        }
    }
    for(int i=0;i<=n;i++){
        for(int j=0;j<=m;j++){
            for(int i_=0;i_<i;i_++){
                for(int j_=0;j_<j;j_++){
                    if(n%2==1&&i==n&&i_==n-1){
                        continue;
                    }
                    C[i][j]+=f[i][i_]*f[j][j_]%mod*fsp(2,j_*(i-i_),mod)%mod*B[i-i_][j-j_]%mod*(A[i_][j_]-C[i_][j_]+mod)%mod;
                    C[i][j]%=mod;
                }
            }
        }
    }
    LL ans=0;
    for(int i=0;i<=m;i++){
        ans+=f[m][i]*(A[n][i]-C[n][i])%mod;
    }
    cout<<(ans%mod+mod)%mod;
    return 0;
}

标签:le,CF1605F,dbinom,二进制位,LL,mid,解题,序列,PalindORme
来源: https://www.cnblogs.com/artalter/p/16439265.html