题目概述
给出
n
个数和
解题报告
我太菜了,都是JZdalao教我题目的……
刚开始我想拆分素因子然后背包……发现直接爆炸。
实际上我们预处理出 K 的因子,然后定义 f[i][j] 表示前 i 个数组成 K 的第 j 个因子的方案数(将因子由小到大排序)就可以了。至于确定因子标号,我用了二分。
解题报告
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=1000,maxs=10000,MOD=1e9+7;
int te,n,K,a[maxn+5],p[maxs+5],f[maxn+5][maxs+5];
void Make()
{
p[0]=0;
for (int i=1,S=sqrt(K);i<=S;i++) if (K%i==0)
{p[++p[0]]=i;if (i*i!=K) p[++p[0]]=K/i;}
sort(p+1,p+1+p[0]);
}
inline int Find(int x)
{
int L=1,R=p[0];
for (int mid=L+(R-L>>1);L<=R;mid=L+(R-L>>1))
{
if (p[mid]==x) return mid;
if (x<p[mid]) R=mid-1; else L=mid+1;
}
return 0;
}
inline void AMOD(int &x,int tem) {if ((x+=tem)>=MOD) x-=MOD;}
int main()
{
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
for (scanf("%d",&te);te;te--)
{
int nn;scanf("%d%d",&nn,&K);n=0;Make();
for (int i=1,x;i<=nn;i++)
{scanf("%d",&x);x=Find(x);if (x) a[++n]=x;}
f[0][1]=1;
for (int i=1;i<=n;i++)
for (int j=1;j<=p[0];j++)
{
f[i][j]=f[i-1][j];if (p[j]%p[a[i]]) continue;
AMOD(f[i][j],f[i-1][Find(p[j]/p[a[i]])]);
}
printf("%d\n",f[n][p[0]]);
}
return 0;
}