这个题,比赛的时候分析出来了,但是最后时间不够了,就没有做出来,GG了,最后补题的时候有因为自己地粗心开始不断debug,不过也发现问题了。
先来说一下思路,将这个数分解后使其乘积最大,且因子各不相同,我就想到了阶乘,但是一个数不一定可以分解的彻底,所以可以将其从后向前均分到每一个数上,可以想一下,前面的数每增加1其实就是相比于原乘积增加一倍的后面数的乘积。然后分析一下时间复杂度,发现必须直接计算,就考虑用阶乘预处理,然后因为可能分解过后的数不连续,就用阶乘 乘 缺的那个数的逆元。
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long LL;
const int MAXN = 1e6;
LL fa[MAXN + 10];
const LL mod = 1e9 + 7;
void pre()
{
fa[1] = 1;
for(int i = 2;i <= MAXN;++i)
fa[i] = (fa[i - 1] * i) % mod;
}
LL quick_pow(LL a,LL b)
{
LL ans = 1;
while(b)
{
if(b&1) ans = (ans * a) % mod;
a = (a * a) % mod;
b>>=1;
}
return ans;
}
LL inv(LL n)
{
return quick_pow(n,mod - 2);
}
int main()
{
int T;
scanf("%d",&T);
pre();
while(T--)
{
LL n;
scanf("%lld",&n);
if(n <= 4)
{
printf("%d\n",n);
continue;
}
LL l = 2;
LL r = ( sqrt( 1 + 8 * n) - 1) / 2.0;
//cout << r << endl;
LL yu = n - (LL)((r) / 2.0 * (r + 1) - 1);
if( yu >= r + 1) yu -= r + 1,r++;
LL len = r - l + 1;
l += yu / len; r+= yu / len;
yu %= len;
LL m = r - yu;
if(yu) r = r + 1;
LL k1 = (fa[m] * inv(fa[l - 1])) % mod;
LL k2 = yu > 0 ? (fa[r] * inv(fa[m + 1])) % mod : 1;
LL ans = (k1 * k2) % mod;
printf("%d\n",ans);
}
return 0;
}