hdu 5646 DZY Loves Partition 二分+数学分析+递推

时间:2022-07-27 20:42:03

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5646

题意:将n分成k个正整数之和,要求k个数全部相同;并且这k个数的乘积最大为多少?结果mod 1e^9+7;

思路:由于是mod,不能通过模拟进行比较来判断是否为最优解;那么我们就必须直接计算出这个最优解的序列;

由于当a <= b-2时(相等时表示中间空一位),a*b < (a+1)*(b-1);所以最优解序列要不就是一串连续的序列,要不就是中间空一位,分成两段连续的序列;

因为如果存在空格超过1个的两个数,就可以通过加1减1,移到相邻或者只空一个位;

注意:到底空的是哪一位,与平均值并不相关;这需要看n与确定的左边界之后的k个数的和相差的值;(用二分确定左边界,使得sum[a,...a+k) <= n < sum[a...a+k]);

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define inf 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1|1
typedef pair<int,int> PII;
#define A first
#define B second
#define MK make_pair
typedef __int64 ll;
template<typename T>
void read1(T &m)
{
T x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
m = x*f;
}
template<typename T>
void read2(T &a,T &b){read1(a);read1(b);}
template<typename T>
void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
template<typename T>
void out(T a)
{
if(a>) out(a/);
putchar(a%+'');
} const int mod = 1e9+;
int add(ll a, ll b) { return (a+b)%mod; }
int sub(ll a, ll b) { return ((a-b)%mod + mod)%mod; }
int mult(ll a, ll b) { return ((a * b))%mod; }
ll n,k;
int s[];
int main()
{
int T;
read1(T);
while(T--){
read2(n,k);
if(n < k*(k+)/){//
puts("-1");
continue;
}
int tmp = n/k,a,l = ,r = tmp;
while(l <= r){
int mid = l+r>>;
if((mid+mid+k-)*k/ <= n) a = mid,l = mid+;
else r = mid - ;
}
int sum = (a+a+k-)*k/;// a即为确定的左边界
ll ans = ;
if(sum == n){
rep0(i,,k) ans= mult(ans,a+i);
}
else{
int t = n - sum;
int cnt = k-t;
rep0(i,,cnt) ans = mult(ans,a+i);
a++;//中间空一位
while(cnt < k)
ans = mult(ans,a+cnt),cnt++;
}
printf("%d\n",ans);
}
return ;
}