这张图就已经能提供很多样例了。
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; }