HDU5976-Detachment(乘法逆元+贪心)

题目链接

Problem Description

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:
1Two different small line segments cannot be equal ( aiaj when i≠j).
2Make 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

1
4

Sample Output

4

题目大意

一个数分成若干不同的正整数,让他们的乘积最大。

思路

参考:https://blog.csdn.net/qq_34374664/article/details/53466435

https://blog.csdn.net/kevin66654/article/details/53065169

1=1
2=2
3=3
4=4
5=2+3
6=2+3+1=2+4
7=2+3+2=3+4
8=2+3+3=2+3+1+2=3+5
9=2+3+4
10=2+3+4+1=2+3+5
11=2+3+4+2=2+3+4+1+1=2+4+5
12=2+3+4+3=2+3+4+1+1+1=3+4+5
13=2+3+4+4=2+3+4+1+1+2=3+4+6
14=2+3+4+5
15=2+3+4+5+1=2+3+4+6
先试着写几个数,从2开始写(1对乘积没有贡献),如果刚好写完,那这些数的乘积就是结果,比如5=2+3。

有余数的情况,比如11=2+3+4+2,把2分开加在最后的两个数3和4上,11=2+4+5。

还有一种情况比较特殊,比如13=2+3+4+4=3+4+5+1,还剩1加在最后一个数上,13=3+4+6。

分配完后得到下面这个式子

①2*3*...*(i-1)*(i+1)*...*k*(k+1)

②3*4*...*i*(i+1)*...*k*(k+2)

用数组记录前n项乘积,取余的时候出现(a/b)%mod,乘法(a*b)%mod=(a % mod) * (b % mod),除法取余需要用到乘法逆元。

a/b ≡ a/b * b * x ≡ a * x (mod p)   想法是将除法变成乘法,结果还一样。找到这样一个x。那么就需要 b*x≡1 (mod p),由费马小定理 a^{p} ≡ a (mod p) ,p为质数,得到a^{p-1} ≡ 1 (mod p),即a * a^{p-2} ≡ 1 (mod p),x就可以取 b^{p-2}。因此a/b(mod p)可以转化为a*b^{p-2}(mod p)。

上述条件是p为质数,1e9+7和1e9+9都是质数,因此可以使用。如果非质数,需要用扩展欧几里得计算b*x≡1(mod p),把x给算出来。

写完之后总是WA,但是测试数据也没发现什么问题,一遍一遍提交后发现.....每次乘积之后,都需要加%mod,(abc)%mod是不可以的,需要a*b%mod * c %mod,乘一次就需要取余一次。应该是某个数据恰好爆了,才会错。还遇到了一个沙雕的问题,我把快速幂命名为pow,和math库的pow重名了,每次调用的是math库的pow,= =。

在找位置的时候,用二分,可以自己写,也可以用upper_bound( begin,end,num)  。 lower_bound( )和upper_bound( )用法


#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;

const int Max = 1e5+5;
const int mod = 1e9 + 7;

ll sum[Max+10],mul[Max+10];
int x;

ll qpow(ll a,ll b)
{
    ll ans = 1;
    while(b)
    {
        if(b&1) ans = ans*a%mod;
        a = a*a%mod;
        b >>= 1;
    }
    return ans;
}

void init()
{
    sum[1] = 0;
    mul[1] = 1;
    for(int i=2;i<=Max;i++){
        sum[i] = sum[i-1] + i;
        mul[i] = (i*mul[i-1])%mod;
    }
}

int b_search(int x)
{
    int l=1,r=Max-5,mid;
    while(l<=r)
    {
        mid = (l+r)/2;
        if(sum[mid]==x) return mid;
        if(sum[mid]<x) l = mid + 1;
        else r = mid - 1;
    }
    return r;//没有的值,r x l,返回左边的r值
}

int main()
{
    init();
    int T; scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&x);
        if(x<=4){
            printf("%d\n",x);
            continue;
        }
        //int k = b_search(x); //二分查找
        int k = upper_bound(sum+1,sum+1+Max,x)-sum-1;//
        int m = x - sum[k];//余数
        ll ans;
        if(k==m)
            ans =  mul[k] * qpow(2,mod-2)%mod * (k+2)%mod;
        else
            ans = mul[k+1] * qpow(k-m+1,mod-2)%mod %mod;
        printf("%lld\n",ans);
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值