51nod-猴猴吃香蕉【dp】

mac2026-06-14  15

正题

题目链接:https://www.51nod.com/Contest/Problem.html#contestProblemId=1149


题目大意

n n n个数,求有多少种选择方案使选择的数乘机为 k k k


解题思路

显然 k k k的质因数最多只有 9 9 9个,我们将质因数进行 d p dp dp。若选择的数的质因数刚好是 k k k的质因数,那么就可以。

为了方便我们将状态压成一维的即可。


c o d e code code

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=1100,XJQ=1e9+7; struct node{ ll w,v; }q[N]; bool cmp(node x,node y) {return x.w<y.w;} ll n,K,v[N],sum[N],f[N*N],T,cnt,two; void dfs(ll x,ll s,ll zs) { if(x>cnt){ (f[zs]+=f[s])%=XJQ; return; } for(ll i=q[x].v-v[x];i>=0;i--) dfs(x+1,s+sum[x-1]*i,zs+sum[x-1]*(i+v[x])); } int main() { scanf("%lld",&T); while(T--){ scanf("%lld%lld",&n,&K);cnt=0; for(ll i=2;i*i<=K;i++){ if(!(K%i)){ q[++cnt].w=i; q[cnt].v=0; while(!(K%i)) q[cnt].v++,K/=i; } } if(K!=1) q[++cnt].w=K,q[cnt].v=1; sort(q+1,q+1+cnt,cmp); memset(f,0,sizeof(f)); f[0]=sum[0]=two=1; for(ll i=1;i<=cnt;i++) sum[i]=sum[i-1]*(q[i].v+1); for(ll i=1;i<=n;i++){ ll x=0,z=0,l=0,r=1; bool flag=0; scanf("%lld",&x); if(x==1){ two=two*2%XJQ; continue; } memset(v,0,sizeof(v)); for(ll j=2;j*j<=x;j++){ if(!(x%j)){ while(q[l].w<j) r*=v[l],l++; if(q[l].w!=j){flag=1;break;} while(!(x%j)) x/=j,v[l]+=(q[l].w==j); if(v[l]>q[l].v){flag=1;break;} } } if(flag) continue; if(x!=1){ for(l=0,r=1;q[l].w<x;r*=v[l],l++); if(q[l].w==x)v[l]++; } dfs(1,0,0); } printf("%lld\n",(f[sum[cnt]-1]*two)%XJQ); } }
最新回复(0)