hdu 5646 DZY Loves Partition 二分+数学分析+递推
Posted hxer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 5646 DZY Loves Partition 二分+数学分析+递推相关的知识,希望对你有一定的参考价值。
链接: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=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;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>9) out(a/10); putchar(a%10+‘0‘); } const int mod = 1e9+7; 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[55]; int main() { int T; read1(T); while(T--){ read2(n,k); if(n < k*(k+1)/2){// puts("-1"); continue; } int tmp = n/k,a,l = 1,r = tmp; while(l <= r){ int mid = l+r>>1; if((mid+mid+k-1)*k/2 <= n) a = mid,l = mid+1; else r = mid - 1; } int sum = (a+a+k-1)*k/2;// a即为确定的左边界 ll ans = 1; if(sum == n){ rep0(i,0,k) ans= mult(ans,a+i); } else{ int t = n - sum; int cnt = k-t; rep0(i,0,cnt) ans = mult(ans,a+i); a++;//中间空一位 while(cnt < k) ans = mult(ans,a+cnt),cnt++; } printf("%d\n",ans); } return 0; }
以上是关于hdu 5646 DZY Loves Partition 二分+数学分析+递推的主要内容,如果未能解决你的问题,请参考以下文章
hdu 5646 DZY Loves Partition 二分+数学分析+递推
HDU 5647DZY Loves Connecting(树DP)