zoukankan      html  css  js  c++  java
  • #4713. 方程

    题目描述

    题解

    考虑最高位 $k$ ,如果 $m_i$第 $k$ 位为 $1$ ,且 $x_i$ 第 $k$ 位为 $0$ 的话,那其他的 $x$ 可以取任意值,因为 $x_i$ 可以取到 $[0,2^k)$ 的任意一个数,所以可以调整一下,据此我们可以列出dp: $f_{i,j}$ 表示前 $i$ 个数,有 $j$ 个数第 $k$ 位为 $1$ ,可以得到方程的解的组数,那如果 $m_i$为 $1$ 的话可以列出转移式子 $f_{i,j}=f_{i-1,j} imes 2^k+f_{i-1,j-1} imes (m_i-2^k+1)$ ,最后要记得除以 $2^k$ 因为其他数确定了,这个数也就确定了,所以只有 $ imes 1$ 的贡献,然后继续递归即可

    效率: $O(30Tn^2)$

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int P=1e9+7;
    int n,m,a[55],f[55][55],w[55];
    int solve(int x){
        if (x<0) return 1;
        f[0][0]=1;int u=0,v=0;
        for (int i=1;i<=n;i++)
            if (a[i]&(1<<x)){
                u++;f[u][0]=1ll*f[u-1][0]*(1<<x)%P;
                for (int j=1;j<=u;j++)
                    (f[u][j]+=(1ll*f[u-1][j]*(1<<x)%P+1ll*f[u-1][j-1]*((a[i]&((1<<x)-1))+1)%P)%P)%=P;
            }
            else for (int j=0;j<=u;j++) f[u][j]=1ll*f[u][j]*((a[i]&((1<<x)-1))+1)%P;
        for (int i=0;i<u;i++)
            if ((i&1)==((m>>x)&1))
                (v+=1ll*f[u][i]*w[x]%P)%=P;
        for (int i=0;i<=u;i++)
            for (int j=0;j<=u;j++) f[i][j]=0;
        if ((u&1)==((m>>x)&1))
            return (v+solve(x-1))%P;
        return v;
    }
    int main(){
        w[0]=1;w[1]=(P+1)>>1;
        for (int i=2;i<55;i++)
            w[i]=1ll*w[i-1]*w[1]%P;
        while(~scanf("%d%d",&n,&m)){
            for (int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            printf("%d
    ",solve(30));
        }
        return 0;
    }
  • 相关阅读:
    SQL*PLUS命令的使用大全
    Oracle总结
    SQL*PLUS命令的使用大全
    Java经典面试题
    学习Java的30个基本概念
    Java经典面试题
    学习Java的30个基本概念
    Oracle总结
    ORACLE大数据量下的分页解决方法
    XAMPP修改80和443端口及创建虚拟目录
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12283476.html
Copyright © 2011-2022 走看看