zoukankan      html  css  js  c++  java
  • hdu 5976 Detachment 脑洞题 猜结论

    题目链接

    题意

    (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]),接下来:

    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
    "); 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;
    }
    
    
  • 相关阅读:
    java学习(一)
    linux下java环境配置
    移动平台开发团队展示
    VS的安装项目:解决安装后注册表中程序信息InstallLocation为空的问题
    .NET将数据导出到Excel表(如何指定默认文件名)
    Linux Shell编程入门
    http与WebSocket
    git push时报错filename too long的解决
    js中传统事件绑定模拟现代事件处理
    对三次握手的理解
  • 原文地址:https://www.cnblogs.com/kkkkahlua/p/7669171.html
Copyright © 2011-2022 走看看