题目:http://poj.org/problem?id=3421
记忆化搜索竟然水过去了。仔细一想时间可能有点不对,但还是水过去了。
#include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; const int N=(1<<20)+5; int n; ll a[N],f[N]; void find(int x) { if(a[x])return; a[x]=1; for(ll i=2;i*i<=x;i++) if(x%i==0) { find(i);find(x/i); ll tmp=a[x]; a[x]=max(a[x],max(a[i],a[x/i])+1); if(a[x]!=tmp)f[x]=0; if(a[i]==a[x]-1)f[x]+=f[i]; if(i!=x/i&&a[x/i]==a[x]-1)f[x]+=f[x/i];//i!=x/i } if(!f[x])f[x]=1; } int main() { while(scanf("%d",&n)==1) { find(n); printf("%lld %lld ",a[n],f[n]); } return 0; }
然后发现是质因数分解。
可以理解成需要乘一个数才能进一步,为了走最长的,就是乘最小的,也就是一个质因数。
方案数就是一堆组合数相乘啦。不敢预处理,现求阶乘也没爆。
没错,仔细一想最多只有20个质因数,因为是log的。
#include<iostream> #include<cstdio> #include<cstring> #define ll long long const int N=(1<<19)+5,M=25; int n,p[M],k[M],tot,sum; ll ans; ll C(int n,int m) { ll ret=1; for(int i=n-m+1;i<=n;i++)ret*=i; for(int i=2;i<=m;i++)ret/=i; return ret; } int main() { while(scanf("%d",&n)==1) { ans=1;sum=0;tot=0; for(int i=2;i*i<=n;i++) if(n%i==0) { p[++tot]=i;k[tot]=0; while(n%i==0)n/=i,k[tot]++; sum+=k[tot]; } if(n>1)p[++tot]=n,k[tot]=1,sum++; printf("%d ",sum); for(int i=1;i<=tot;i++) { ans*=C(sum,k[i]);sum-=k[i]; } printf("%lld ",ans); } return 0; }