zoukankan      html  css  js  c++  java
  • 送分题 [组合计数]

    送分题


    color{red}{正解部分}

    考虑每一位对答案的贡献, 在长度为 NN 的序列中, 现在计算第 bitbit 位的答案,
    bitbit 位 为 11 的数量为 n1n_1, 为 00 的数量为 n0n_0, x+y=Nx+y = N,

    对答案的贡献为 (i=1n1 [i%2=1](Ni)xi)×(i=0n0(Ni)xi)left(sumlimits_{i=1}^{n_1} [i\%2 =1]egin{pmatrix} N \ i end{pmatrix}x^i ight) imes left( sumlimits_{i=0}^{n_0}egin{pmatrix} N \ i end{pmatrix}x^i ight) .

    根据 二项式定理 化第二项为: (x+1)n0(x+1)^{n_0} .

    将第一项化为: i=0n1 ((1)i+1+1)(Ni)xi2frac{sumlimits_{i=0}^{n_1} left((-1)^{i+1}+1 ight) egin{pmatrix} N \ i end{pmatrix}x^i}{2}

    将括号拆开得到: i=0n1(Ni)(x)i+i=0n1(Ni)xi2frac{-sumlimits_{i=0}^{n_1}egin{pmatrix} N \ iend{pmatrix}(-x)^i+sumlimits_{i=0}^{n_1} egin{pmatrix} N \ iend{pmatrix}x^i}{2}

    再使用 二项式定理 继续化简得到: (x+1)n1+(x+1)n12frac{-(-x+1)^{n_1} + (x+1)^{n_1}}{2}

    ans=bit=030(x+1)n1+(x+1)n12×(x+1)n0×2bit herefore ans = sumlimits_{bit=0}^{30} frac{-(-x+1)^{n_1} + (x+1)^{n_1}}{2} imes (x+1)^{n_0} imes 2^{bit} .

    color{red}{实现部分}

    #include<bits/stdc++.h>
    #define reg register
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 1e5 + 10;
    const int mod = 998244353;
    
    int N;
    int M;
    int A[maxn];
    int pw[maxn];
    int s[32][maxn];
    
    int Ksm(int a, int b){ int s=1; while(b){if(b&1)s=1ll*s*a%mod;a=1ll*a*a%mod;b>>=1;} return s; }
    
    void Work(){
            int l = read(), r = read(), x = read(), Ans = 0;
            for(reg int bit = 30; bit >= 0; bit --){
                    int n1 = s[bit][r] - s[bit][l-1], n0 = r-l+1-n1;
                    int res = (Ksm(x+1, n1) - Ksm((1-x+mod)%mod, n1) + mod) % mod;
                    res = 1ll*res*Ksm(2, mod-2) % mod;
                    res = 1ll*res * Ksm(x+1, n0) % mod;
                    res = 1ll*res*pw[bit] % mod;
                    Ans = (Ans + res) % mod;
            }
            printf("%d
    ", Ans);
    }
    
    int main(){
            N = read(), M = read();
            for(reg int i = 1; i <= N; i ++) A[i] = read();
            pw[0] = 1; for(reg int i = 1; i <= 30; i ++) pw[i] = 2ll*pw[i-1] % mod;
            for(reg int i = 0; i <= 30; i ++)
                    for(reg int j = 1; j <= N; j ++){
                            if(A[j] & (1 << i)) s[i][j] ++;
                            s[i][j] += s[i][j-1];
                    }
            for(reg int i = 1; i <= M; i ++) Work();
            return 0;
    }
    
  • 相关阅读:
    编译资源收集
    volatile和synchronized到底啥区别?多图文讲解告诉你
    沙雕与大婶 | Mock掉你的外部依赖吧
    全网最详细的一篇Flutter 尺寸限制类容器总结
    一篇带你看懂Flutter叠加组件Stack
    【MySQL】:事务四大特性与隔离级别
    Dubbo 入门-细说分布式与集群
    Java 线程基础知识
    SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」
    搭建博客、自己的小窝?快来看看这些开源静态网站生成器
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822427.html
Copyright © 2011-2022 走看看