组合数问题。表示现在不会。dp写个。感谢波神教会我优化。。。不然死都过不鸟。。。
每种因子在转移时数目是一样的,可以预处理。但是三重循环必然超时,因为是从前一行转移到后一行,每次可以先处理出所有情况,可减少一重循环。
关于取余还逗b了下,认为当dp恰好为INF整数倍时取余为0,会导致答案为0,实际上答案就是0。。。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
#define LL long long
#define INF 1000000007
#define N 1000
int p[32000];
int r[100000];
int v[5000];
int ptr;
int n,a[N];
void prime(){
memset(r, 0, sizeof(r));
ptr = 0;
for(int i = 2; i < 32000; i++){
if(r[i] == 0)p[ptr ++] = i;
for(int j = 0; j < ptr; j++){
if(i * p[j] < 32000)r[i * p[j]] = 1;
}
}
}
LL dp[505][20000];
LL sum[20000];
int main(){
prime();
scanf("%d", &n);
memset(v, 0, sizeof(v));
for(int i = 0; i < n; i++){
scanf("%d", &a[i]);
int ul = sqrt(a[i]);
int j;
for(j = 0; p[j] <= ul && j < ptr && a[i] != 1; j ++){
if(a[i] % p[j] == 0){
a[i] /= p[j];
v[j] ++;
j --;
}
}
if(a[i] > 1){
for(;j < ptr;j++){
if(a[i] == p[j]){v[j]++;a[i] = 1;break;}
}
if(a[i] > 1){p[ptr] = a[i];v[ptr] = 1;ptr++;}//可能出现比sqrt(a[i])大的因子,在素数数组末尾加上即可,后面不会重复添加
}
}
LL tot = 1;
for(int j = 0; j <= 20000; j++){
sum[j] = 1;
}
for(int i = 1; i <= n; i++){
for(int j = 0; j < 20000; j++){
if(j == 0)dp[i][j] = 1;
else dp[i][j] = sum[j];
}
for(int j = 0; j < 20000; j++){
if(j == 0)sum[j] = 1;
else sum[j] = (sum[j - 1] + dp[i][j]) % INF;//记得取余
}
}
for(int i = 0; i < ptr; i++){
tot = tot * dp[n][v[i]] % INF;
}
printf("%I64d\n", tot);
return 0;
}