一些总结:
1)一个数字若是分成任意数字求乘积和最大,则尽量全部分成3
2)分成两个则是n/2
3)拆成n个,拆成这个数/n
4)不能重复,则优先拆为2,3,4…,剩余▲x从后往前平分。
逆元应用:https://www.cnblogs.com/WHLdbk/p/6051706.html
求逆元:
inv[1]=1;//1的逆元显然是1
for(i=2;i<n;i++)
inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD
#include<bits/stdc++.h>
#define max 1000000000
#define MOD (1000000007LL)
//const __int64 MOD=1000000007;//不能用define定义MOD否则会出错,define是一个函数
using namespace std;
__int64 f[45000];
int sum[45000];
int inv[45000];
void del()
{
inv[1]=1;f[1]=1;sum[1]=0;
for (int i = 2; i<45000; i++)
{
inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;///乘法逆元
f[i]=(f[i-1]*i)%MOD;///前缀乘(在取余MOD的环境下,配合后面的乘法逆元)
sum[i]=sum[i-1]+i;///前缀和(从2开始)
}
//printf("%d %d %d xxx\n",inv[2],inv[3],inv[1]);
return;
}
int main()
{
int T,n,k,l,r,mid;
__int64 ans;
del();
while(~scanf("%d",&T))
{
while(T--)
{
scanf("%d",&n);
if(n<5)printf("%d\n",n);
else
{
l=2;r=45000;mid=(l+r)>>1;
while(l+1<r) ///二分查找
{
if(sum[mid]>n)
r=mid,mid=(r+l)>>1;///r定义为开,不取状态
else
l=mid,mid=(r+l)>>1;///l定义为闭,取状态
}
k=n-sum[l];///printf("%d %d %d xx",sum[l],k,inv[l+1-k]);
if(2+k>l)
ans=f[l]*inv[2]%MOD*(k+2)%MOD,printf("%I64d\n",(ans+MOD)%MOD);
else
ans=f[l]*inv[l+1-k]%MOD*(l+1)%MOD,printf("%I64d\n",(ans+MOD)%MOD);
}
}
}
return 0;
}