hdu 5976 Detachment

来源:互联网 发布:知乎专栏怎么投稿 编辑:程序博客网 时间:2024/05/22 04:34

http://acm.hdu.edu.cn/showproblem.php?pid=5976




拆数字,并求所拆的数字乘积的最大值,显然是拆成2*3*4*5*。。。*n这样的形式,但会存在
多出来的数字,如果多出来的数字加上2能够等于n+1,则答案就是2*3*。。。*n/2*(n+1),
如果小于n+1,则可以将多出来的数加到前面的3或者4或者5或者后面的数上,是的所加的那个数加上多出来的数字后正好等于n+1,则答案就是2*3*4*5*....*n/(i)*n+1,可以预处理打表前缀和和前缀积,并且除法取模需要用到乘法逆元。





#include<iostream>#include<cstdio>using namespace std;long long int MOD=7+1e9;int  qzh[55555];long long int qzj[55555];int ny[55555];void ycl(){qzj[1]=1;qzh[1]=0;ny[1]=1;for(int i=2;i<=48888;i++){ny[i]=(MOD-MOD/i)*ny[MOD%i]%MOD;qzj[i]=(i*qzj[i-1])%MOD;qzh[i]=i+qzh[i-1];} } int main(){int t;long long int ans;int a;int lef,rig,mid;    while(scanf("%d",&t)!=EOF)    {ycl();while(t--){scanf("%d",&a);if(a<5)printf("%d\n",a);else {lef=2;rig=48888;mid=(lef+rig)>>1;while(lef+1<rig){if(qzh[mid]>a){rig=mid;mid=(lef+rig)>>1;}else{lef=mid;mid=(lef+rig)>>1;}}int dy=a-qzh[lef];if(2+dy>=lef+1)ans=qzj[lef]*ny[2]%MOD*(2+dy)%MOD;else ans=qzj[lef]*ny[lef+1-dy]%MOD*(lef+1)%MOD;ans=(ans+MOD)%MOD;printf("%lld\n",ans);} } }return 0;}