zoukankan      html  css  js  c++  java
  • uoj 300 [CTSC2017]吉夫特

    题目传送门

      戳此处转移

    题目大意

      给定一个长为$n$的序列,问它有多少个长度大于等于2的子序列$b_{1}, b_{2}, cdots, b_{k}$满足$prod_{i = 2}^{k}C_{b_{i - 1}}^{b_{i}} equiv 1 pmod{2}$。答案模$10^{9} + 7$

      考虑限制条件,即前后两个数$b_{i - 1}, b_{i}$,它们要满足$C_{b_{i - 1}}^{b_{i}} equiv 1pmod{2}$。

      这样不好处理,考虑使用Lucas定理,得到$b_{i - 1}$是$b_{i}$的子集的结论。

      然后是个常规动态规划,用$f[i][s]$表示考虑到第$i$位,最后一个数是$s$的方案数。但是这样时间复杂度$O(n^{2})$。

      考虑分块,每个位置将它的子集信息上传。

      然后修改和查询一个枚举前9位,一个枚举后9位就行了。

      一直不知道所有数互不相同的意义。

      然后直到今天,发现可以直接枚举子集,$O(3^{left lceil log_{2}W ight ceil})$。

    Code

     1 /**
     2  * uoj
     3  * Problem#300
     4  * Accepted
     5  * Time: 400ms
     6  * Memory: 2956k
     7  */
     8 #include <bits/stdc++.h>
     9 using namespace std;
    10 typedef bool boolean;
    11 
    12 const int S = 1 << 9, M = 1e9 + 7;
    13 const int maskL = (1 << 9) - 1, maskH = maskL << 9, mask = maskL | maskH;
    14 
    15 int n;
    16 int *ar;
    17 int f[S][S];
    18 
    19 inline void init() {
    20     scanf("%d", &n);
    21     ar = new int[(n + 1)];
    22     for (int i = 1; i <= n; i++)
    23         scanf("%d", ar + i);
    24 }
    25 
    26 inline int query(int S) {
    27     int rt = 0, s0 = S & maskL, s1 = (S & maskH) >> 9, ms1 = s1 ^ maskL;
    28     for (int s = ms1; s; s = (s - 1) & ms1)
    29         rt = (rt + f[s | s1][s0]) % M;
    30     return (rt + f[s1][s0]) % M;
    31 }
    32 
    33 inline void modify(int S, int val) {
    34     int s0 = S & maskL, s1 = (S & maskH) >> 9;
    35     for (int s = s0; s; s = (s - 1) & s0)
    36         f[s1][s] = (f[s1][s] + val) % M;
    37     f[s1][0] = (f[s1][0] + val) % M;
    38 }
    39 
    40 int res = 0;
    41 
    42 inline void solve() {
    43     modify(mask, 1);
    44     for (int i = 1, c; i <= n; i++) {
    45         c = query(ar[i]);
    46         res = (res + c) % M;
    47         modify(ar[i], c);
    48     }
    49     res = (res - n + M) % M;
    50     printf("%d", res);
    51 }
    52 
    53 int main() {
    54 //    freopen("gift.in", "r", stdin);
    55     init();
    56     solve();
    57     return 0;
    58 }
  • 相关阅读:
    3.5---用栈实现队列(CC150)
    3.3---集合栈(CC150)
    3.2---最小栈(CC150)
    3.1---一个数组实现三个栈(CC150)
    2.7---判断链表是否是回文(CC150)
    SpringCloud实战5-Feign声明式服务调用
    Spring Cloud(二):服务注册与发现 Eureka【Finchley 版】
    Spring Cloud Eureka 自我保护机制
    Spring Cloud Edgware新特性之七:可选的EnableDiscoveryClient注解
    Spring Cloud 声明式服务调用 Feign
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8483454.html
Copyright © 2011-2022 走看看