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

转载于:https://www.cnblogs.com/kkkkahlua/p/7669171.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值