zoukankan      html  css  js  c++  java
  • #3211. 吉夫特

    题目描述

    简单的题目,既是礼物,也是毒药。

    B 君设计了一道简单的题目,准备作为 gift 送给大家。

    输入一个长度为 $n$ 的数列 $a_1, a_2 , dots, a_n$ 问有多少个长度大于等于 $2$ 的不上升的子序列 $a_{b_1}, a_{b_2}, ldots, a_{b_k}$ 满足

    $$ prodlimits_{i = 2} ^ k inom{a_{b_{i - 1}}}{a_{b_i}} mod 2 = inom{a_{b_1}}{a_{b_2}} imes inom{a_{b_2}}{a_{b_3}} imes cdots imes inom{a_{b_{k - 1}}}{a_{b_k}}mod 2 > 0 $$

    输出这个个数对 $1000000007$ 取模的结果。

    题解

    考虑 $ ext{Lucas}$ 定理, $(_m^n)=(_{m\%2}^{n\%2})(_{m/2}^{n/2})$,列举一下,发现只有 $(_1^0)=0$ ,说明要满足 $(_m^n)$ 是奇数那必须 $m And n=m$,

    所以我们可以考虑暴力: $f[i][s]$ 表示前 $i$ 个数, $s$ 值为末尾的方案数,然后暴力枚举即可,效率不是很优,发现 $s le 2^18$ ,于是我们可以考虑把 $s$ 分前 $9$ 位和后 $9$ 位,即 $f[i][j][k]$ 表示前 $i$ 个数,最后的状态的前 $9$ 位为 $j$ ,后 $9$ 位的子集为 $k$ 的方案数的总和,这样效率就是 $O(2^9n)$ 了

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int P=1e9+7;
    int n,f[512][512],s;
    int main(){
        cin>>n;
        for (int x,y,v,i=1;i<=n;i++){
            scanf("%d",&x);
            y=x&511;x>>=9;v=f[x][y];
            for (int j=x;j<512;j=(j+1)|x)
                (f[x][y]+=f[j][y])%=P;
            (f[x][y]+=1)%=P;
            v=(P-v+f[x][y])%P;(s+=(v+P-1)%P)%=P;
            for (int j=(y-1)&y;j;j=(j-1)&y)
                (f[x][j]+=v)%=P;
            if (y) (f[x][0]+=v)%=P;
        }
        cout<<s<<endl;return 0;
    }
  • 相关阅读:
    mybatis中crud操作范例
    Guava----Function
    Spring mvc Controller接口
    简单的验证码识别(opecv)
    Mat转换为QImage
    将多张图片无缝拼接方法
    模式识别---图像二值化
    双边过滤算法
    C++对于大型图片的加载缩放尝试
    ijg库解码超大型jpeg图片
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12313713.html
Copyright © 2011-2022 走看看