还是比较简单的233
发现质因数分解之后就是每次乘一个质因数组成的链
所以链长质因数分解之后指数相加即可
方案数就是当前剩几种就推一位
但是显然不能递推 发现组合一下就是组合数(n,m) * (n-m,k) * (n-m-k,r) * .... * (lst,0)
再组合一下就是和的阶乘除以阶乘的和
发现和最多是20不会爆ll 于是AC
Code:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<vector> #define ms(a,b) memset(a,b,sizeof a) #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define inf 2147483647 using namespace std; typedef long long ll; ll read() { ll as = 0,fu = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') fu = -1; c = getchar(); } while(c >= '0' && c <= '9') { as = as * 10 + c - '0'; c = getchar(); } return as * fu; } const int N = 2000005; //head int mindiv[N],prime[83000]; void initprime(int n) { rep(i,2,n) { if(!mindiv[i]) prime[++prime[0]] = i; for(int j = 1;j <= prime[0] && i * prime[j] <= n;j++) { mindiv[i * prime[j]] = prime[j]; if(i % prime[j] == 0) break; } } } ll fac[N]; void initfac(int n) { fac[0] = 1; rep(i,1,n) fac[i] = fac[i-1] * i; } int val[22]; int sum; ll ans; void div(int n) { rep(i,1,prime[0]) { int tmp = 0; while(n % prime[i] == 0) { n /= prime[i]; tmp++; } sum += tmp; val[tmp]++; if(n == 1) break; } } int main() { int n; initprime(1<<20); initfac(21); while(~scanf("%d",&n)) { sum = 0; ms(val,0); if(n == 1) { printf("1 1 "); continue; } div(n); printf("%d ",sum); ans = fac[sum]; rep(i,1,20) while(val[i]) ans /= fac[i],val[i]--; printf("%lld ",ans); } return 0; }