题意:
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
2
4
5
Sample Output
4
6
翻译成汉语就是给出一个数T代表T组样例,然后每组样例给出一个x,然后将x拆分成任意多个各不相同的数a1,a2a1,a2, … 满足(x= a1+a2a1+a2+…) ,怎样拆分才能使得这些数的乘积最大,输出最大值并取模1e9+7
思路:
我们先特判a为1的情况,输出1
对于a>1的情况:
由于拆分出的数各不相同,因此我们可以求sum[i]数组代表2 + 3 + … + i(i >= 2),ans[i]代表2✖️3✖️…✖️i (i >= 2,注意累成需取模1e9+7否则爆longlong)。至于为什么不含1,因此任何数满足n > (n - 1)✖️1,所以拆成1不划算。
我们利用二分找到第一个大于等于a的sum[i],此时需要分类讨论:
若sum[i] == a,则直接输出ans[i]即为答案
若sum[i] - a == 1,则去掉2和i(也就是用ans[i]分别乘2和i关于1e9+7的逆元),再乘(i + 1)并取模1e9+7即为答案
若sum[i] - a > 1,我们设sum[i] - a为k,k一定小于等于i,我们直接去掉k即可(也就是ans[i]乘k关于1e9+7的逆元)并取模1e9+7即为答案
代码:
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <algorithm>
#define d int32_t
#define ll int64_t
#define N 45000
#define mem(a) memset(a, 0, sizeof(a))
#define For(i, star, endd) for(d i = star; i <= endd; i++)
using namespace std;
d sum[N + 5];
ll ans[N + 5];
const ll mod = 1e9 + 7;
//预处理sum与ans数组
void init() {
mem(sum);
ans[1] = 1;
For(i, 2, N) {
sum[i] += sum[i - 1] + i;
ans[i] = ans[i - 1] * i % mod;
}
}
//扩展欧几里得
ll exten(ll a, ll b, ll &x, ll &y) {
if(a == 0 && b == 0) return -1;
if (b == 0) {
x = 1;
y = 0;
return a;
}
ll t = exten(b, a % b, y, x);
y -= a / b * x;
return t;
}
//求逆元
ll mod_reverse(ll a, ll n) {
ll x, y;
ll t = exten(a, n, x, y);
if (t == 1) return (x % n + n) % n;
return -1;
}
//二分查找第一个大于等于val的sum[i]下角标
d erfen(d val) {
d l = 2, r = N, mid;
while (l <= r) {
mid = (l + r) >> 1;
if(sum[mid] >= val) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return l;
}
d main () {
init();
d T, a;
scanf("%d", &T);
while (T--) {
scanf("%d", &a);
if (a == 1) { //特判当a为1时
printf("1\n");
continue;
}
d inx = erfen(a);
d t = sum[inx] - a;
if (t == 0) { //分三种情况讨论
printf("%lld\n", ans[inx]);
} else if (t == 1) {
d k = inx + 1;
ll res = ans[inx] * mod_reverse(2, mod) % mod * mod_reverse(inx, mod) % mod * k % mod;
printf("%lld\n", res);
} else {
ll res = ans[inx] * mod_reverse(t, mod) % mod;
printf("%lld\n", res);
}
}
return 0;
}
如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢