• 题解 SP2829 【TLE


    题目链接

    Solution TLE - Time Limit Exceeded

    题目大意:给定 (n,m),和长为 (n) 的序列 (c),让你构造一个长为 (n) 的序列 (a),满足 (a[i]in [0,2^m))(c[i] mid a[i])(forall i in [0,n),a[i] ;and;a[i+1]=0)

    高维前缀和


    分析:很容易列出一个 (dp) 式子

    (f(i,S)) 表示序列前 (i) 项,末尾为 (S) 的方案数

    那么 (f(i,S)=sum f(i-1,S')),其中 (S' in [0,2^m)) 满足 (S;and;S'=0)

    由于是子集求和,相比直接枚举子集,高维前缀和是一个更好的方法

    在二维前缀和中,有基于容斥原理的写法

    for(int i = 1;i <= n;i++)
    	for(int j = 1;j <= m;j++)
        	f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1] + v[i][j];
    

    这样在低维可行,在高维复杂度将会呈指数级增长

    for(int i = 1;i <= n;i++)
    	for(int j = 1;j <= m;j++)
        	v[i][j] += v[i - 1][j];
    for(int i = 1;i <= n;i++)
    	for(int j = 1;j <= m;j++)
        	v[i][j] += v[i][j - 1];
    

    子集求和的高维前缀和,本质上就是第二种写法的位运算优化

    for(int d = 0;d < m;d++)//枚举维度
    	for(int s = 0;s < (1 << m);s++)
        	if(s & (1 << d))v[s] += v[s ^ (1 << d)];
    

    于是我们可以优化到 (O(nm2^m))

    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int maxn = 64,maxm = 1 << 17,mod = 1e9;
    inline int add(int a,int b){return (a + b) % mod;}
    inline int mul(int a,int b){return (1ll * a * b) % mod;}
    int f[maxn][maxm],n,m,c[maxn],t;
    inline void solve(){
        scanf("%d %d",&n,&m);
        for(int i = 1;i <= n;i++)scanf("%d",&c[i]);
        memset(f,0,sizeof(f));
        f[0][0] = 1;
        for(int d = 0;d < m;d++)
            for(int s = 0;s < (1 << m);s++)
                if(s & (1 << d))f[0][s] = add(f[0][s],f[0][s ^ (1 << d)]);
        for(int i = 1;i <= n;i++){
            for(int s = 0;s < (1 << m);s++)
                if(s % c[i])f[i][s] = f[i - 1][((1 << m) - 1) & (~s)];
            for(int d = 0;d < m;d++)
                for(int s = 0;s < (1 << m);s++)
                    if(s & (1 << d))f[i][s] = add(f[i][s],f[i][s ^ (1 << d)]);
        }
        printf("%d
    ",f[n][(1 << m) - 1]);
    }
    int main(){
        scanf("%d",&t);
        while(t--)solve();
        return 0;
    }
    
  • 相关阅读:
    添加Google Admob到ANDROID应用中
    linux命令及实例说明一:cd、ls、rmdir、rm、mkdir
    android中dip、dp、px、sp和屏幕密度
    在程序中读取ANDROID应用的程序名称和版本号
    linux常用命令及实例二:cp、mv、chown、chmod、find
    Android开发,常用的终端命令
    eclipse里配置solr开发测试环境
    自定义Dialog之Progress(二)
    android 判断网络状态
    hive cli命令行选项
  • 原文地址:https://www.cnblogs.com/colazcy/p/13917236.html
Copyright © 2020-2023  润新知