zoukankan      html  css  js  c++  java
  • 【题解】选数字 [51nod1354]

    【题解】选数字 [51nod1354]

    传送门:选数字 ([51nod1354])

    【题目描述】

    (T) 组测试点,每一组给定一个长度为 (n) 的序列和一个整数 (K),找出有多少子序列满足子序列中所有元素乘积恰好等于K,答案对 (1e9+7) 取模。

    【样例】

    样例输入:
    2
    3 3
    1 1 3
    3 6
    2 3 6
    
    样例输出:
    4
    2
    

    【数据范围】

    (100\%) (1 leqslant T leqslant 20,) (1 leqslant N leqslant 1000,) (2 leqslant K leqslant 10^8,) (1 leqslant a[i] leqslant K)

    【分析】

    考虑 (01) 背包,用 (dp[j]) 表示乘积等于 (j) 的子序列数,原序列中的 (n) 个数就是 (n) 个物品,其数值就是体积。

    (K) 的范围有 (10^8) 辣莫大,但是会对答案造成影响的只有一部分可整除 (K) 的数的 (dp) 值,所以还可以优化。

    为防止爆空间,(dp) 数组开 (map) 类型,用指针访问,并且保证里面存的决策点都是可以整除 (K) 的数,每次要加入新的物品时判断一下,只有当物品体积 (a)(a) 乘以决策点都可整除 (K) 时,才让该物品使用该决策点。
    (dp[a*x]+=dp[x](a|K,x|K,a*x|K))

    时间复杂度为 (O(T*n*p)),其中 (p)(K) 的正约数个数。

    【Code】

    #include<algorithm>
    #include<cstdio>
    #include<map>
    #define Re register int
    using namespace std;
    const int P=1e9+7;
    const int N=1003;
    int x,n,K,T,t,o,a;
    map<int,int>dp,tmp;
    map<int,int>::iterator it;
    inline void in(Re &x){
        int f=0;x=0;char c=getchar();
        while(c<'0'||c>'9')f|=c=='-',c=getchar();
        while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
        x=f?-x:x;
    }
    int main(){
        in(T);
        while(T--){
        	in(n),in(K);
        	dp.clear();
        	for(Re i=1;i<=n;++i){
                in(a);
                if(K%a)continue;
                tmp=dp;
                for(it=tmp.begin();it!=tmp.end();++it)
                	if(a<=K/(x=it->first)&&K/x%a==0)
                        (dp[a*x]+=it->second)%=P;
                (dp[a]+=1)%=P;
        	}
        	printf("%d
    ",dp[K]);
        }
    }
    
  • 相关阅读:
    Java知识15 Number&Math类【多测师】
    python callable()方法实例
    高级super实例
    高级any、for组合用法
    python 字典update、setdefault、pop方法案例
    一个经典的python字典生成式案例
    一个发挥到极致的yield案例
    python map使用
    Python yield详解
    django __path__使用
  • 原文地址:https://www.cnblogs.com/Xing-Ling/p/11348073.html
Copyright © 2011-2022 走看看