hdu 5976 Detachment

时间:2022-08-05 13:49:26

Detachment

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 392    Accepted Submission(s):
131

Problem Description
In a highly developed alien society, the habitats are
almost infinite dimensional space.
In the history of this planet,there is an
old puzzle.
You have a line segment with x units’ length representing one
dimension.The line segment can be split into a number of small line segments:
ahdu 5976 Detachment1hdu 5976 Detachment,ahdu 5976 Detachment2hdu 5976 Detachmenthdu 5976 Detachment

, … (x= ahdu 5976 Detachment1hdu 5976 Detachment+ahdu 5976 Detachment2hdu 5976 Detachmenthdu 5976 Detachment

+…) assigned to different dimensions. And then, the multidimensional space has
been established. Now there are two requirements for this space:
1.Two
different small line segments cannot be equal ( ahdu 5976 Detachmentihdu 5976 Detachmentahdu 5976 Detachmentjhdu 5976 Detachmenthdu 5976 Detachment

when i≠j).
2.Make this multidimensional space size s as large as possible
(s= ahdu 5976 Detachment1hdu 5976 Detachment∗ahdu 5976 Detachment2hdu 5976 Detachmenthdu 5976 Detachment

*...).Note that it allows to keep one dimension.That's to say, the number of ai
can be only one.
Now can you solve this question and find the maximum size of
the space?(For the final number is too large,your answer will be modulo
10^9+7)

 
Input
The first line is an integer T,meaning the number of
test cases.
Then T lines follow. Each line contains one integer
x.
1≤T≤10^6, 1≤x≤10^9
 
Output
Maximum s you can get modulo 10^9+7. Note that we wants
to be greatest product before modulo 10^9+7.
 
Sample Input
1
4
 
Sample Output
4
 
Source
 
题意:有一个数字n,将它拆分成m个数,这m个数相加等于n,且这m个数各不相同  问怎样拆分使得这m个数的乘积最大,输出这个最大的乘积值
将n拆成 2 3 4 5 6 7 8 9 .........l +r 这样的形式,这样可以保证m的个数尽量多,因为m的个数多的话,得到的乘积明显大,现在就是这个r的值,倘若r刚好为0,
则n无多余,则这个乘积一定最大,如果r>0的话
我们只需要通过x+r=l+1 找到x 理由如下
2  3  4  5       1
如果把1加到小的值上 乘积是最大的,3*3*4*5=180;
当加到最大的数上的话  2*3*4*6=144
证明省略 
做一个预处理,求前缀和,和累积
以下有一个有关逆元的 
利用
inv[1]=1;
for(i=2;i<=n;i++)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;求出每个数的逆元

2 3 4 5 6 7 8 9 ......l  +r
b[i]=(b[i-1]*i)%mod;
比如2+r>l
结果只需要ans=b[l]*inv[2]*(2+r);
因为2在做累积进行了取模运算 所以不能直接除2,要乘以她的逆元
 
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string.h>
#include<map>
#define INF 1000000000
#define LETTER 26
#define SIZE 45000
#define pi 3.14159265358979
typedef long long ll;
typedef unsigned long long LL;
using namespace std;
const long long mod=INF+;
int a[SIZE],inv[SIZE];
ll b[SIZE];
int low,high,mid;
void f(){
a[]=;
b[]=;
inv[]=;
for(int i=;i<=SIZE;i++){
a[i]=a[i-]+i;
b[i]=(b[i-]*i)%mod;
inv[i]=(mod-mod/i)*inv[mod%i]%mod; }
}
void erfen(int n){
low=,high=SIZE;
while(low+<high){
mid=(low+high)>>;
if(n>=a[mid]) low=mid;
else high=mid;
}
}
int main(){
int i,j,k;
int t;
int n;
f();
ll ans;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
if(n<=){cout<<n<<endl;continue;}
erfen(n);
int l=low,r=n-a[l];
if(+r>l){
ans=b[l]*inv[]%mod*(+r)%mod;
}
else{
k=l+-r;
ans=b[l]*inv[k]%mod*(l+)%mod;
}
printf("%lld\n",(ans+mod)%mod); } }