51nod 1354【DP】
(我一定是A了一题假DP)
给定序列a[0],a[1],a[2],...,a[n-1] 和一个整数K时,
有多少子序列所有元素乘起来恰好等于K。
K<=1e8;
思路:
感觉 k 的 约数是突破口,首先个数 少。
直接维护一个 到 i 的时候 各个约数 的 个数。(约数 类似 背包)。
#include<bits/stdc++.h> using namespace std; typedef long long LL; const LL mod=1e9+7; const int N=1e3+10; int num,a[N]; map<int,int>mp; vector<int>xs; vector<LL>dp; void init(int n) { dp.clear(); mp.clear(); xs.clear(); mp[1]=1; mp[n]=1; xs.push_back(1);dp.push_back(0); xs.push_back(n);dp.push_back(0); int q=sqrt(n),p; for(int i=2;i<=q;i++) { if(n%i) continue; p=n/i; mp[p]=1; mp[i]=1; xs.push_back(i);dp.push_back(0); if(i!=p) { xs.push_back(p);dp.push_back(0); } } sort(xs.begin(),xs.end()); } int main() { int n,T,k; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k); init(k); int ind,sz,temp,ind2; sz=xs.size(); for(int i=0;i<n;i++) { scanf("%d",&a[i]); if(mp.find(a[i])==mp.end()) continue; ind=lower_bound(xs.begin(),xs.end(),a[i])-xs.begin(); for(int j=sz-1;j>=ind;j--) { if((xs[j] % a[i])==0) { temp=xs[j] / a[i]; ind2=lower_bound(xs.begin(),xs.end(),temp)-xs.begin(); dp[j]=(dp[ind2]+dp[j])%mod; } } dp[ind]=(dp[ind]+1LL)%mod; } printf("%lld\n",dp[sz-1]); } return 0; }