码迷,mamicode.com
首页 > 其他好文 > 详细

【题解】选数字 [51nod1354]

时间:2019-08-13 20:29:56      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:getc   http   等于   cond   include   分析   长度   std   getchar   

【题解】选数字 [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\n",dp[K]);
    }
}

【题解】选数字 [51nod1354]

标签:getc   http   等于   cond   include   分析   长度   std   getchar   

原文地址:https://www.cnblogs.com/Xing-Ling/p/11348073.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!