hdu 5976 Detachment 脑洞题 猜结论

题目链接

题意

\(x\)拆成\(a_1+a_2+...+\)的形式,且\(a_1\lt a_2\lt...\),使得\(a_1*a_2*...\)取到最大值

思路

大胆猜结论。

首先拆分的形式中肯定不能有\(1\).

于是预处理出前缀和\(a[i]=\sum_{k=2}^{i}k\)

找到\(\geq x\)的最小的\(a[id]\),接下来:

  1. 如果\(a[id]==x\),意味着\(2+3+...+id=x\),那么答案就是\(2*3*...*id=factorial(id)\)
  2. 否则,求和时就省去超过部分对应的项\(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\n"); 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\n", ans);
}
int main() {
    init();
    int T;
    scanf("%d", &T);
    while (T--) work();
    return 0;
}

posted @ 2017-10-15 00:31  救命怀  阅读(189)  评论(0编辑  收藏  举报