這個題,比賽的時候分析出來了,但是最後時間不夠了,就沒有做出來,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;
}