HDU 5646 DZY Loves Partition(二分法)

DZY Loves Partition

 
 Accepts: 154
 
 Submissions: 843
 Time Limit: 4000/2000 MS (Java/Others)
 
 Memory Limit: 262144/262144 K (Java/Others)
Problem Description

DZY loves partitioning numbers. He wants to know whether it is possible to partition nn into the sum of exactly kk distinct positive integers.

After some thinking he finds this problem is Too Simple. So he decides to maximize the product of these kk numbers. Can you help him?

The answer may be large. Please output it modulo 10^9+7109+7.

Input

First line contains tt denoting the number of testcases.

tt testcases follow. Each testcase contains two positive integers n,kn,k in a line.

(1\le t\le 50, 2\le n,k \le 10^91t50,2n,k109)

Output

For each testcase, if such partition does not exist, please output -11. Otherwise output the maximum product mudulo 10^9 + 7109+7.

Sample Input
4
3 4
3 2
9 3
666666 2
Sample Output
-1
2
24
110888111


     
     
     
     
Hint
In 1st testcase, there is no valid partition. In 2nd testcase, the partition is 3=1+23=1+2. Answer is 1\times 2 = 21×2=2. In 3rd testcase, the partition is 9=2+3+49=2+3+4. Answer is 2\times 3 \times 4 = 242×3×4=24. Note that 9=3+3+39=3+3+3 is not a valid partition, because it has repetition. In 4th testcase, the partition is 666666=333332+333334666666=333332+333334. Answer is 333332\times 333334= 111110888888333332×333334=111110888888. Remember to output it mudulo 10^9 + 7109+7, which is 110888111110888111.
大体题意:
给你个数n,拆k个各不相同的数之和,并且使得k个数的乘积最大,最后输出k个数乘积对1e9+7取模的结果!
思路:
令sum(a,b),为a + (a + 1) + (a + 2)....+b的结果!
先取得的一个数a使得sum(a,a+k-1)刚好小于n,
最后多出来的数字加到这一串数后面,每个数加1就行了!
通过二分来查找最大的a
二分:
先对n取半,如果此时sum(a,a+k-1)比n大,则向左找,否则向右找,并且记录最大值MAX
如果最后发现MAX 没变的话,则不存在一个a满足式子,则直接输出-1
否则就用那个a即可!
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
ll sum(ll a,ll b){
    ll num = b-a+1;
    ll ans;
    ans = num%2 ? (a+b)/2*num : num/2*(a+b);
    return ans;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        ll n,k;
        scanf("%lld%lld",&n,&k);
        ll MAX = -1;
        ll a,l=1,r=n;
        while(l <= r){
            ll mid =(r+l)/2;
            ll tmp = sum(mid,mid+k-1);
            if (tmp > n)r = mid-1;
            if (tmp <= n){
                l = mid + 1;
                if (tmp > MAX){
                    MAX = tmp;
                    a = mid;
                }
            }
        }
        if (MAX == -1){
            printf("-1\n");
            continue;
        }
        ll tp = n-MAX;
        ll ans = 1;
        for (int i = a; i < a+k; ++i){
            if (i >= a+k-tp)ans=(ans%mod*((i+1)%mod)%mod)%mod;
            else ans = (ans %mod * i%mod)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}


你可能感兴趣的:(C语言)