首先預處理,分解爲n位數至少要多大,然後upper_bound大概就知道拆分爲幾個數了.
然後考慮最優解,就是每位數勁量的大,因爲是相乘,所以中間做多有一個空,我們記錄中間空的位置和其實位置以及最後的位置就知道了答案.
前面的數的階乘以及逆元可以預處理,階乘的逆元也可以預處理.複製度在O(logn)
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
const int maxn = 5e4;
const int mod = 1e9+7;
using namespace std;
int sum2[maxn+10];
ll fac[maxn+10];
ll inv[maxn+10];
void init(){
sum2[0] = sum2[1] = 0;
fac[0]=fac[1]=1;
for(int i = 2; i < maxn; i++){
fac[i]= fac[i-1]*i%mod;
sum2[i] = sum2[i-1] + i;
}
inv[1] = 1;
for(int i = 2; i < maxn; i++){
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
}
void e_gcd(int a, int b, ll &d, ll &x, ll &y){
if(!b){
d = a; x = 1; y = 0;
return ;
}
e_gcd(b, a%b, d, y, x);
y -= x*(a/b);
}
int main(){
init();
int t;scanf("%d",&t);
while(t--){
int n;scanf("%d",&n);
if(n==1){
printf("1\n");
continue;
}
//拆分位數
int it = upper_bound(sum2, sum2+maxn, n) - sum2 -2;
n-=sum2[it+1];
//提升位數
int stx, stlen, edlen, edy, temp;
stx = 2 + n/it;
edy = 1+it + (n/it) + (n%it!=0);
edlen = n%it;
if(edlen)temp = edy - edlen;
else temp = 0;
ll x,y,d;
e_gcd(fac[stx-1],mod, d, x, y);
if(edlen){
printf("%lld\n",((fac[edy]*inv[temp]%mod+mod)%mod*x%mod+mod)%mod);
}else{
printf("%lld\n",(fac[edy]*x%mod+mod)%mod);
}
}
return 0;
}