题解 P3773 【[CTSC2017]吉夫特】

笑着哭i 提交于 2020-03-12 13:45:43

做这题的前置知识是 Lucas 定理,可以先做一下这题

我就当大家都会 Lucas 定理了awa。


Lucas 定理:

\[ C^m_n\!\equiv\!C^{\left\lfloor\frac{m}{p}\right\rfloor}_{\left\lfloor\frac{n}{p}\right\rfloor}\times C^{m\mod p}_{n\mod p}\pmod{p} \]

所以我们来看看原式:

\[ \prod_{i=2}^k \dbinom{a_{b_i}}{a_{b_{i-1}}}\!\mod 2 \]

重点就在于 \(\!\mod 2\) 这个地方。

由 Lucas 定理可知,原式的答案不是 0,就是 1。

所以我们要保证 \(\forall \dbinom{a_{b_i}}{a_{b_{i-1}}} \equiv 1 \pmod 2\)

又因为 \(\dbinom{0}{0}\)\(\dbinom{1}{0}\)\(\dbinom{1}{1}\) 为 1,\(\dbinom{0}{1}\) 为 0。

根据 Lucas 定理,每次 \(\mod 2\) 相当于把 \(a_{b_i}\)\(a_{b_{i-1}}\) 二进制拆分,并且保证,\(a_{b_i}\) 为 0 的那个位上 \(a_{b_{i-1}}\) 不能为 1。

\(a_{b_{i}}\!\And a_{b_{i-1}}\!=\!a_{b_i}\),我们设 \(f(i)\) 为以 \(i\) 开头的子序列数,枚举子集进行 dp 即可。

\(p.s.\) 在最后累加的时候,要减去只有一个数的情况。

代码如下:

#include<bits/stdc++.h>
#define rint register int
using namespace std;
inline int read(){
    int s=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
    while(c>='0'&&c<='9')s=(s<<1)+(s<<3)+c-48,c=getchar();
    return f?s:-s;
}
const int Mod=1e9+7;
int n,a[300010],f[300010],ans;
int main(){
    n=read();
    for(rint i=1;i<=n;++i) a[i]=read();
    for(rint i=n;i;--i){
        for(rint j=(a[i]-1)&a[i];j;j=(j-1)&a[i])
            f[a[i]]=(f[a[i]]+f[j])%Mod;
        f[a[i]]=(f[a[i]]+1)%Mod;
    }
    for(rint i=1;i<=n;++i) ans=(ans+f[a[i]]-1)%Mod;
    printf("%d",ans%Mod); 
    return 0;
}

没了awa。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!