题目链接
题意
将(x)拆成(a_1+a_2+...+)的形式,且(a_1lt a_2lt...),使得(a_1*a_2*...)取到最大值
思路
大胆猜结论。
首先拆分的形式中肯定不能有(1).
于是预处理出前缀和(a[i]=sum_{k=2}^{i}k),
找到(geq x)的最小的(a[id]),接下来:
- 如果(a[id]==x),意味着(2+3+...+id=x),那么答案就是(2*3*...*id=factorial(id))
- 否则,求和时就省去超过部分对应的项(a[id]-x),即$$2+3+...+(a[id]-x-1)+(a[id]+x+1)+...+id=x$$答案就是(factorial(id)/(a[id]-x))
且慢!如果超过的部分是(1),本来就不在求和项中怎么办啊?
(继续猜)那么就将(2)省去,再给最后一项加上(1),即(3+4+...+(id-1)+(id+1)=x),答案就是(factorial(id-1)/2*(id+1)).
就此,三种情况完毕,猜完,(A)了。
Code
#include <bits/stdc++.h>
#define maxn 50000
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
LL a[maxn+10], fac[maxn+10];
LL poww(LL a, LL b) {
LL ret = 1;
while (b) {
if (b & 1) (ret *= a) %= mod;
(a *= a) %= mod;
b >>= 1;
}
return ret;
}
void init() {
a[0] = a[1] = 0, a[2] = 2;
for (int i = 3; i <= maxn; ++i) a[i] = a[i-1] + i;
fac[1] = 1;
for (int i = 2; i <= maxn; ++i) fac[i] = fac[i-1] * i % mod;
}
void work() {
int n;
scanf("%d", &n);
if (n == 1) { printf("1
"); return; }
int id = lower_bound(a, a+maxn, n) - a;
LL ans;
if (a[id] == n) ans = fac[id];
else if (a[id]-n > 1) ans = fac[id] * poww(a[id]-n, mod-2) % mod;
else ans = fac[id-1] * poww(2, mod-2) % mod * (id+1) % mod;
printf("%lld
", ans);
}
int main() {
init();
int T;
scanf("%d", &T);
while (T--) work();
return 0;
}