zoukankan      html  css  js  c++  java
  • Luogu3214 [HNOI2011]卡农

    Luogu3214 [HNOI2011]卡农

    题面:Luogu

    解析

    题意即为选出(m)个不同的数,使其异或和为0,发现其实就是先选前(m-1)个数,然后最后一个数应该等于前面所有数的异或和,这样计算两种不合法的情况:1.最后一个数为0。2.最后一个数与前面的数重复。先看1,发现是选(m-1)个数异或和为0,再看2,考虑删去重复的2个数,重复的数的位置有(m-1)中,取值有(S-(i-2))中(因为不能与其他的数重复),那么剩下的(m-2)个数异或和应为0。那么设(f(i))表示选(i)个数异或和为0的方案数,有:

    [f(i)=C[S][i-1]-f[i-1]-(S-i+2)(i-1)f[i-2] ]

    最后注意需要消除顺序的影响。

    代码

    
    // luogu-judger-enable-o2
    #include<cstdio>
    #define N 1000005
    using namespace std;
    const int P=100000007;
    inline int In(){
        char c=getchar(); int x=0,ft=1;
        for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1;
        for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
        return x*ft;
    }
    int n,m,pow_2,_inv,A[N],f[N];
    inline int power(int x,int k){
        int s=1,t=x;
        for(;k;k>>=1,t=1ll*t*t%P) if(k&1) s=1ll*s*t%P;
        return s;
    }
    int main(){
        n=In(); m=In(); pow_2=(power(2,n)-1+P)%P;
        _inv=1; for(int i=1;i<=m;++i) _inv=1ll*i*_inv%P; _inv=power(_inv,P-2);
        A[1]=pow_2; for(int i=1;i<m;++i) A[i+1]=1ll*(pow_2-i+P)%P*A[i]%P;
        f[0]=1; for(int i=2;i<=m;++i) f[i]=((A[i-1]-f[i-1]+P)%P-1ll*(pow_2-i+2+P)%P*(i-1)%P*f[i-2]%P+P)%P;
        printf("%lld
    ",1ll*f[m]*_inv%P);
        return 0;
    }
    
    
    
  • 相关阅读:
    tomcat 支持https
    linux环境下jdk 安装以及maven私服搭建
    消息中间间初识
    HDU 5527 Too Rich
    HDU 5534 Partial Tree
    HDU 5543 Pick The Sticks
    HDU 5542 The Battle of Chibi dp+树状数组
    CodeForces 842D Vitya and Strange Lesson
    Codeforces 858D Polycarp's phone book
    HDU 5489 Removed Interval
  • 原文地址:https://www.cnblogs.com/pkh68/p/10596933.html
Copyright © 2011-2022 走看看