题意:
将n拆成a1+a2+a3+…+ax的形式(ai≠aj),让a1*a2*a3*…*ax的值最大,求这个最大值
找规律
n=35:2+3+4+5+6+7+8; max:2*3*4*5*6*7*8
n=36:2+3+4+5+6+7+8+1; max:2*3*4*5*6*7*9
n=37:2+3+4+5+6+7+8+2; max:2*3*4*5*6*8*9
n=38:2+3+4+5+6+7+8+3; max:2*3*4*5*7*8*9
n=39:2+3+4+5+6+7+8+4; max:2*3*4*6*7*8*9
n=40:2+3+4+5+6+7+8+5; max:2*3*5*6*7*8*9
n=41:2+3+4+5+6+7+8+6; max:2*4*5*6*7*8*9
n=42:2+3+4+5+6+7+8+7; max:3*4*5*6*7*8*9
n=43:2+3+4+5+6+7+8+8; max:3*4*5*6*7*8*10
n=41:2+3+4+5+6+7+8+9; max:3*4*5*6*7*8*9*10(一波循环)
……
阶乘和乘法逆元都打表(打到100000就够了),每次计算把中间缺的那个除掉
寻找临界点用二分
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define mod 1000000007
#define LL long long
LL jc[100005] = {1,1}, er[100005] = {0,0,2}, nv[100005];
LL Pow(LL x, LL y)
{
LL sum = 1;
while(y)
{
if(y%2)
sum = sum*x%mod;
x = x*x%mod;
y /= 2;
}
return sum;
}
int main(void)
{
LL T, i, n, x, r;
for(i=2;i<=100000;i++)
jc[i] = (jc[i-1]*i)%mod;
for(i=3;i<=100000;i++)
er[i] = er[i-1]+i;
for(i=2;i<=100000;i++)
nv[i] = Pow(i, mod-2);
scanf("%lld", &T);
while(T--)
{
scanf("%lld", &n);
if(n<=4)
{
printf("%lld\n", n);
continue;
}
x = lower_bound(er+1, er+100001, n)-er;
if(er[x]==n)
printf("%lld\n", jc[x]);
else
{
r = n-er[x-1];
if(r==x-1)
printf("%lld\n", jc[x-1]*(x+1)%mod*nv[2]%mod);
else
printf("%lld\n", jc[x]*nv[x-r]%mod);
}
}
return 0;
}