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: a1,a2, … (x= a1+a2+…) 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 ( ai≠aj when i≠j).
2.Make this multidimensional space size s as large as possible (s= a1∗a2*...).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
题目大意
一个数分成若干不同的正整数,让他们的乘积最大。
思路
参考:https://blog.youkuaiyun.com/qq_34374664/article/details/53466435
https://blog.youkuaiyun.com/kevin66654/article/details/53065169
1=1
2=2
3=3
4=4
5=2+3
6=2+3+1=2+4
7=2+3+2=3+4
8=2+3+3=2+3+1+2=3+5
9=2+3+4
10=2+3+4+1=2+3+5
11=2+3+4+2=2+3+4+1+1=2+4+5
12=2+3+4+3=2+3+4+1+1+1=3+4+5
13=2+3+4+4=2+3+4+1+1+2=3+4+6
14=2+3+4+5
15=2+3+4+5+1=2+3+4+6
先试着写几个数,从2开始写(1对乘积没有贡献),如果刚好写完,那这些数的乘积就是结果,比如5=2+3。
有余数的情况,比如11=2+3+4+2,把2分开加在最后的两个数3和4上,11=2+4+5。
还有一种情况比较特殊,比如13=2+3+4+4=3+4+5+1,还剩1加在最后一个数上,13=3+4+6。
分配完后得到下面这个式子
①2*3*...*(i-1)*(i+1)*...*k*(k+1)
②3*4*...*i*(i+1)*...*k*(k+2)
用数组记录前n项乘积,取余的时候出现(a/b)%mod,乘法(a*b)%mod=(a % mod) * (b % mod),除法取余需要用到乘法逆元。
a/b ≡ a/b * b * x ≡ a * x (mod p) 想法是将除法变成乘法,结果还一样。找到这样一个x。那么就需要 b*x≡1 (mod p),由费马小定理 ≡ a (mod p) ,p为质数,得到
≡ 1 (mod p),即a *
≡ 1 (mod p),x就可以取
。因此a/b(mod p)可以转化为a*
(mod p)。
上述条件是p为质数,1e9+7和1e9+9都是质数,因此可以使用。如果非质数,需要用扩展欧几里得计算b*x≡1(mod p),把x给算出来。
写完之后总是WA,但是测试数据也没发现什么问题,一遍一遍提交后发现.....每次乘积之后,都需要加%mod,(abc)%mod是不可以的,需要a*b%mod * c %mod,乘一次就需要取余一次。应该是某个数据恰好爆了,才会错。还遇到了一个沙雕的问题,我把快速幂命名为pow,和math库的pow重名了,每次调用的是math库的pow,= =。
在找位置的时候,用二分,可以自己写,也可以用upper_bound( begin,end,num) 。 lower_bound( )和upper_bound( )用法
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
const int Max = 1e5+5;
const int mod = 1e9 + 7;
ll sum[Max+10],mul[Max+10];
int x;
ll qpow(ll a,ll b)
{
ll ans = 1;
while(b)
{
if(b&1) ans = ans*a%mod;
a = a*a%mod;
b >>= 1;
}
return ans;
}
void init()
{
sum[1] = 0;
mul[1] = 1;
for(int i=2;i<=Max;i++){
sum[i] = sum[i-1] + i;
mul[i] = (i*mul[i-1])%mod;
}
}
int b_search(int x)
{
int l=1,r=Max-5,mid;
while(l<=r)
{
mid = (l+r)/2;
if(sum[mid]==x) return mid;
if(sum[mid]<x) l = mid + 1;
else r = mid - 1;
}
return r;//没有的值,r x l,返回左边的r值
}
int main()
{
init();
int T; scanf("%d",&T);
while(T--)
{
scanf("%d",&x);
if(x<=4){
printf("%d\n",x);
continue;
}
//int k = b_search(x); //二分查找
int k = upper_bound(sum+1,sum+1+Max,x)-sum-1;//
int m = x - sum[k];//余数
ll ans;
if(k==m)
ans = mul[k] * qpow(2,mod-2)%mod * (k+2)%mod;
else
ans = mul[k+1] * qpow(k-m+1,mod-2)%mod %mod;
printf("%lld\n",ans);
}
return 0;
}