题意:N个人平均分成若干组开party,而且D天一个循环(汗,这开到什么时候),一个循环里每天一组的人数必须不一样,现在给出D,求最小的满足题意的N。
如果知道N,其实D就是N的因子的个数,有多少个不同因子就可以有多少次不同的分组。
求因子数的话将N进行质因数分解,N = a1^p1 * a2^p2 * a3^p3 ...,a是质因子,然后因子数=(p1+1)*(p2+1)*(p3+1)*...
虽然D<10000,但N可能很大,比如D=101,101是质数,所以没得分解,此时最小的N = 2^100,连longlong都爆,预处理这种方案是不可行的。
现在反过来知道D,要求N。按照上面的式子可以想到将D分解成若干个因子得到指数,再将质数分配给质因子就能得到N,但是具体怎么分解最优我就不知道了。。。
比如样例1是分解成最多的个数,而样例2却是分解少的,如果分解成2*2*2得到2^1 * 3^1 * 5^1 = 30,反而更大。
所以我只能采取暴力枚举方案的极端手段了(> < 智商不够了)。
由于每次分解到的因子数并不会太多,所以不用担心暴力的时间。
判断大小我是直接用double乘起来,虽然会丢失一定的精度,但是由于这种指数运算稍微有点不同结果差异挺大的,所以比较还是没什么问题的。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<functional>
#include<cmath>
using namespace std;
const int N = 10010;
bool f[N];
int p[N], a[N], b[N], c[N], n, m, k;
double ans;
void dfs(int x){
if(x==k){
int L = 0;
for(int i=0; i<k; i++){
if(c[i]) b[L++] = c[i]-1;
}
sort(b, b+L, greater<int>());
double cur = 1.0;
for(int i=0; i<L; i++){
cur *= pow(p[i]*1.0, b[i]);
}
if(cur<ans){
ans = cur;
n = L;
for(int i=0; i<n; i++) a[i] = b[i];
}
return;
}
dfs(x+1);
for(int i=x+1; i<k; i++){
c[i] *= c[x];
int tmp = c[x];
c[x] = 0;
dfs(x+1);
c[x] = tmp;
c[i] /= tmp;
}
}
int main(){
m = 0;
memset(f,0,sizeof(f));
for(int i=2; i<N; i++){
if(!f[i]){
p[m++] = i;
for(int j=i<<1; j<N; j+=i) f[j]=1;
}
}
int d;
while(~scanf("%d", &d)){
k = 0;
for(int i=0; i<m && d>1; i++){
if(d%p[i]==0){
while(d%p[i]==0){
d/=p[i];
a[k++] = p[i];
}
}
}
sort(a, a+k, greater<int>());
ans = 1.0;
for(int i=0; i<k; i++){
c[i] = a[i];
a[i]--;
ans *= pow(p[i]*1.0, a[i]);
}
n = k;
dfs(0);
for(int i=0; i<n; i++){
if(i) printf(" * ");
printf("%d^%d", p[i], a[i]);
}
puts("");
}
return 0;
}