这张图就已经能提供很多样例了。
30 : 12
12: 7
24: 10
……
其实我就是一直在纠结确定一个质数之后,选择其他的质数(肯定和它们的个数相关)有多少种方案。
但其实并没我之前甚至用组合数那么复杂。。。
拿24 = 2 * 2 * 2 * 3;
对于 2 来说,它出现三次,那么你就有三种选择方案 2 、 4 、 8。
然后 3 只出现了一次, 你可选可不选【不选其实就选的是1】 那么就是 两种方案。 乘法原理, 枚举2时有 6 个方案。
然后还有 对于3 来说 同理可得你有一种方案 就只能选择 3.
然后 2 出现了三次, 有四种方案, 不选(1)、 2、 4、 8。 共四种方案。
答案就是 10;
综上, 做法就是枚举每个质数, 然后根据它自己的次数和其他质数出现的次数求出对应答案, 答案加和。
这样做就根据了每个数出现的次数来限定乘除来的数一定小于n, 且是n的因子。
上代码。
#include<bits/stdc++.h>
#define ms(x) memset(x, 0, sizeof(x))
#define ll long long
using namespace std;
const int N=1000003;
vector<int>vec;
bool ispri[N];
int pri[100000], o;
void getpri() {
ms(ispri);
for(int i=2; i<=N-2; i++) {
if(!ispri[i]) pri[o++] = i;
for(int j=i+i; j<=N-2; j+=i) {
ispri[j] = 1;
}
}
}
int fatcnt;
ll factor[100][2];
int allsum = 0;
ll getfactors(ll x) {
fatcnt = 0;
ll tmp = x;
for(int i=0; pri[i]<=tmp/pri[i]; i++) {
factor[fatcnt][1] = 0;
if(tmp%pri[i]==0) {
factor[fatcnt][0] = pri[i];
while(tmp%pri[i]==0) {
factor[fatcnt][1]++;
tmp/=pri[i];
}
fatcnt++;
}
}
if(tmp!=1) {
factor[fatcnt][0] = tmp;
factor[fatcnt++][1] = 1;
}
return fatcnt;
}
int main() {
o = 0;
allsum = 0;
int T;
getpri();
scanf("%d",&T);
while(T--) {
ll n;
scanf("%lld", &n);
ll sum = getfactors(n); // allsum
ll ans = 0;
for(int i=0;i<sum;i++){
ll tmp = factor[i][1];
for(int j=0;j<sum;j++){
if(i==j) continue;
else{
tmp *= (factor[j][1] + 1);
}
}
ans += tmp;
}
printf("%lld\n",ans);
}
return 0;
}