HDU-5976

题意:

​ 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;
}

转载请注明出处!!!

如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢

猜你喜欢

转载自blog.csdn.net/Ivan_zcy/article/details/83214134
hdu