[HDU-5976] [Problem F](逆元+二分优化+数学分析)

来源:互联网 发布:怎么在pdf上签名 mac 编辑:程序博客网 时间:2024/06/07 22:15

给定一个数,让你分成互不相等的n个数(n为自然数),使这些数的乘积最大,输出最大乘积。

因为要对1000000007取余,所以要用到逆元

之前的维护一下前缀和,前缀积就可以了

#include <iostream>#include <algorithm>#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <string.h>#include <map>#include <set>#include <queue>#include <deque>#include <list>#include <bitset>#include <stack>#include <stdlib.h>#define lowbit(x) (x&-x)typedef long long ll;using namespace std;const ll mod = 1e9+7;const int max_inv=100000;ll inv[max_inv+5];ll n;ll qmod(ll a,ll b){    ll ans=1;    while(b)    {        if(b&1)        {            ans=(ans*a)%mod;        }        b=b/2;        a=(a*a)%mod;    }    return ans;}void get_inv(){    for(ll i=2; i<=max_inv; i++)    {        inv[i]=qmod(i,mod-2);    }}ll v[44720];ll wei=0;std::vector<ll> num;void get_c(){    ll n=1000000000;    ll k=2;    ll sum=0;    ll ans=1;    while(sum+k<=n)    {        ans=(ans*k)%mod;        num.push_back(ans);        sum=sum+k;        v[wei]=sum;        wei++;        k++;    }}ll solve(){    ll i=upper_bound(v,v+wei,n)-v;    i--;    ll max_num=i+2;    ll k=n-v[i];    ll ans=num[i];    //cout<<max_num<<" "<<k<<" "<<ans<<endl;    if(k==0)    {        return ans;    }    else if(k==max_num)    {        ans=(ans*inv[2])%mod;        ans=(ans*(max_num+2))%mod;    }    else    {        ans=(ans*inv[max_num-k+1])%mod;        ans=(ans*(max_num+1))%mod;    }    return ans;}int main(){    get_inv();    get_c();    int t;    //freopen("data.in","r",stdin);    cin>>t;    while(t--)    {        scanf("%lld",&n);        if(n<5)        {            cout<<n<<endl;            continue;        }        else        {            cout<<solve()<<endl;        }    }    return 0;}