HDU 5976 Detachment

链接

问题

将正整数 n n n 分拆成若干不等的正整数 a i a_i ai,使得 s = ∏ i = 1 r a i s=\prod_{i=1}^ra_i s=i=1rai最大,求最大值对的 1 0 9 + 7 10^9+7 109+7

分拆方案

分拆方案举例

  • 例1: n = 14 n=14 n=14,分拆方案:
    • 2、3、4、5 共4项, s = 2 ∗ 3 ∗ 4 ∗ 5 = 120 s = 2*3*4*5 = 120 s=2345=120
    • 3、5、6 共3项, s = 3 ∗ 5 ∗ 6 = 90 s = 3*5*6 = 90 s=356=90
    • ⋯ ⋯ \cdots\cdots
  • 例2: n = 16 n=16 n=16,分拆方案:
    • 2、3、5、6 共4项, s = 2 ∗ 3 ∗ 5 ∗ 6 = 180 s = 2*3*5*6 = 180 s=2356=180
    • 2、3、4、7 共4项, s = 2 ∗ 3 ∗ 4 ∗ 7 = 168 s = 2*3*4*7 = 168 s=2347=168
    • ⋯ ⋯ \cdots\cdots
  • 例3: n = 18 n=18 n=18,分拆方案:
    • 3、4、5、6 共4项, s = 3 ∗ 4 ∗ 5 ∗ 6 = 360 s = 3*4*5*6 = 360 s=3456=360
    • 4、5、9 共3项, s = 4 ∗ 5 ∗ 9 = 180 s = 4*5*9 = 180 s=459=180
    • ⋯ ⋯ \cdots\cdots
  • 例4: n = 19 n=19 n=19,分拆方案:
    • 3、4、5、7 共4项, s = 2 ∗ 3 ∗ 4 ∗ 5 = 120 s = 2*3*4*5 = 120 s=2345=120
    • 3、5、6 共3项, s = 3 ∗ 5 ∗ 6 = 90 s = 3*5*6 = 90 s=356=90
  • 例5: n = 20 n=20 n=20,分拆方案:
    • 2、3、4、5、6 共5项, s = 2 ∗ 3 ∗ 4 ∗ 5 ∗ 6 = 720 s = 2*3*4*5*6 = 720 s=23456=720
    • ⋯ ⋯ \cdots\cdots

分拆方案总结

  • 分拆方案不含1(贪心思想:1对积无贡献)
  • 对于给定的n,可以得到不含1的最大的分拆数k及其(唯一)方案(贪心思想:每一项尽量小)
    ∑ i = 2 k + 1 i ≤ n < ∑ i = 2 k + 2 i 或 n = ∑ i = 2 k + 1 i + r , 0 ≤ r ≤ k + 1 , 即 : \sum_{i=2}^{k+1}i\leq n < \sum_{i=2}^{k+2}i \quad 或 \quad n=\sum_{i=2}^{k+1}i+r,0\leq r \leq k+1,即: i=2k+1in<i=2k+2in=i=2k+1i+r0rk+1
    n = ∑ i = 2 k + 1 i + r = { 2 + 3 + ⋯ + k + ( k + 1 ) ⏞ k   项 , 当  r = 0 2 + ⋯ + ( k + 1 − r ) ⏞ k − r   项 + ( k + 3 − r ) + ⋯ + ( k + 2 ) ⏞ r   项 , 当  1 ≤ r < k 3 + 4 + ⋯ + ( k + 1 ) + ( k + 2 ) ⏞ k   项 , 当  r = k 3 + 4 + ⋯ + ( k + 1 ) ⏞ k − 1   项 + ( k + 3 ) , 当  r = k + 1 n =\sum_{i=2}^{k+1}i+r= \begin{cases} \overbrace{2+3+\cdots+k+(k+1)}^{k\,项}, & \text{当 $r=0$} \\ \overbrace{2+\cdots+(k+1-r)}^{k-r\,项}+\overbrace{(k+3-r)+\cdots+(k+2)}^{r\,项}, & \text{当 $1\leq r<k$} \\ \overbrace{3+4+\cdots+(k+1)+(k+2)}^{k\,项}, & \text{当 $r=k$} \\ \overbrace{3+4+\cdots+(k+1)}^{k-1\,项}+(k+3), & \text{当 $r=k+1$} \\ \end{cases} n=i=2k+1i+r=2+3++k+(k+1) k,2++(k+1r) kr+(k+3r)++(k+2) r,3+4++(k+1)+(k+2) k,3+4++(k+1) k1+(k+3), r=0 1r<k r=k r=k+1
    特别的,当 n = 4 n=4 n=4 时,则 k = 1 k=1 k=1,即分拆方案为 { 4 } \{4\} {4}
  • 有不含1的最大的分拆数k时,积 s s s 最大。证明如下:
    • n = a 1 + a 2 + ⋯ + a k 且 a 1 < a 2 < ⋯ < a k 且 a 1 = 2   或   3   或   4 n=a_1+a_2+\cdots+a_k 且 a_1 < a_2 < \cdots <a_k且a_1=2\,或\,3\,或\,4 n=a1+a2++aka1<a2<<aka1=234,是不含1的最大分拆数方案
    • n = b 1 + b 2 + ⋯ + b j 且 1 < b 1 < b 2 < ⋯ < b j 且 j < k n=b_1+b_2+\cdots+b_j 且 1 < b_1 < b_2 < \cdots <b_j且j<k n=b1+b2++bj1<b1<b2<<bjj<k,是不含1的分拆方案,则
      ∏ i = 1 j b i < ∏ i = 1 j a i , 即 最 大 分 拆 数 方 案 对 应 的 积 s 最 大 \prod_{i=1}^jb_i < \prod_{i=1}^ja_i,即最大分拆数方案对应的积s最大 i=1jbi<i=1jais
    • 规则1:若 3 < a 1 < a 2 3 < a_1 < a_2 3<a1<a2,则 2 ⋅ ( a 1 − 1 ) ⋅ ( a 2 − 1 ) > a 1 ⋅ a 2 2\cdot (a_1-1) \cdot (a_2-1) > a_1\cdot a_2 2(a11)(a21)>a1a2.
      ∵ 2 ⋅ ( a 1 − 1 ) ⋅ ( a 2 − 1 ) − a 1 ⋅ a 2 = ( a 1 − 2 ) ⋅ a 2 − 2 a 1 + 2 ≥ ( a 1 − 2 ) ⋅ a 2 − 2 a 2 + 2 = ( a 1 − 4 ) ⋅ a 2 + 2 ≥ 2 ∴ 2 ⋅ ( a 1 − 1 ) ⋅ ( a 2 − 1 ) > a 1 ⋅ a 2 , 即 将 2 项 拆 成 3 项 \because \quad 2\cdot (a_1-1) \cdot (a_2-1) - a_1\cdot a_2\\ =(a_1-2)\cdot a_2-2a_1+2\\ \geq (a_1-2)\cdot a_2-2a_2+2\\ =(a_1-4)\cdot a_2+2 \geq 2 \\ \therefore \quad 2\cdot (a_1-1) \cdot (a_2-1) > a_1\cdot a_2, 即将2项拆成3项 2(a11)(a21)a1a2=(a12)a22a1+2(a12)a22a2+2=(a14)a2+222(a11)(a21)>a1a223
    • 规则2:若 4 ≤ a 4\leq a 4a,则 a ≤ 2 ( a − 2 ) a \leq 2(a-2) a2(a2)
      ∵ 2 ( a − 2 ) − a = a − 4 ≥ 0   ∴ a ≤ 2 ( a − 2 ) , 即 将 1 项 拆 成 2 项 \because \quad 2(a-2)-a= a-4 \geq 0\\ \,\\ \therefore \quad a \leq 2(a-2),即将 1 项拆成 2 项 2(a2)a=a40a2(a2)12
    • 规则3:若 1 ≤ a 1 < a 2 1\leq a_1 < a_2 1a1<a2,则 a 1 ∗ a 2 ≤ ( a 1 + 1 ) ( a 2 − 1 ) a_1*a_2 \leq (a_1+1)(a_2-1) a1a2(a1+1)(a21)
      ∵ ( a 1 + 1 ) ( a 2 − 1 ) − a 1 ⋅ a 2 = a 2 − a 1 − 1 ≥ 0   ∴ ( a 1 + 1 ) ( a 2 − 1 ) ≥ a 1 ⋅ a 2 \because \quad (a_1+1)(a_2-1)- a_1\cdot a_2= a_2-a_1-1 \geq 0\\ \,\\ \therefore \quad (a_1+1)(a_2-1) \geq a_1\cdot a_2 (a1+1)(a21)a1a2=a2a110(a1+1)(a21)a1a2
    • 通过规则1-3,将 { b 1 , ⋯   , b j } \{b_1,\cdots,b_j\} {b1,,bj}方案转化为 { a 1 , ⋯   , a k } \{a_1,\cdots,a_k\} {a1,,ak}方案,转化过程中积 s s s 不变小

算法分析

  • 先计算k,利用 2 , 3 , 4 , 5 , ⋯ 2,3,4,5, \cdots 2345 的前缀和和二分搜索计算 k k k
  • 计算 2 ⋯ k   %   m 2\cdots k\,\%\,m 2k%m
  • 分情况计算

代码

  • 扩展欧几里得求逆元
// hdu 5976 Detachment
#include<bits/stdc++.h>
using namespace std;
#define MOD 1000000007
#define MAX 45000
int K[MAX], M[MAX];
// ax + by = (a, b)
int ex_gcd(int a, int b, int &x, int &y){
	int d;
	// a = (a, 0) = (a, b)
	if(b == 0){
		x = 1, y = 0;
		return a;
	}
	// b(y+a/bx) + a%bx = (b, a%b)
	d = ex_gcd(b, a%b, x, y); 
	int tmp = x;
	x = y;
	y = tmp - a/b*y;
	return d;
}
int main(){
	int t, n, k, r, ans, x, y;
	K[1] = 2, M[1] = 2;
	for(int i=2; i < MAX; ++i) K[i] = K[i-1]+i+1;
	for(int i=2; i < MAX; ++i) M[i] = 1LL*M[i-1]*(i+1)%MOD;
	scanf("%d", &t);
	while(t--){
		scanf("%d", &n);
		if(n < 5){
			printf("%d\n", n);
			continue;
		}
		k = lower_bound(K+1, K+MAX, n)-K;
		if(K[k] > n) k--;
		r = n - K[k];
		if(r == 0) ans = M[k];
		else if(r == k){
			ans = M[k+1];
			ex_gcd(2, MOD, x, y);
			ans = 1LL * ans * x % MOD;
		}
		else if(r == k+1){
			ans = M[k];
			ex_gcd(2, MOD, x, y);
			ans = 1LL * ans * x % MOD;
			ans = 1LL * ans * (k+3) % MOD;
		}
		else{
			ans = M[k+1];
			ex_gcd(k+2-r, MOD, x, y);
			ans = 1LL * ans * x % MOD;
		}
		printf("%d\n", (ans+MOD)%MOD);
	}
    return 0;
}
  • 线性求逆元
// hdu 5976 Detachment
#include<bits/stdc++.h>
using namespace std;
#define MOD 1000000007
#define MAX 45000
int K[MAX], M[MAX], inv[MAX];
int main(){
	int t, n, k, r, ans, x, y;
	K[1] = 2, M[1] = 2, inv[1]=1;
	for(int i=2; i < MAX; ++i) K[i] = K[i-1]+i+1;
	for(int i=2; i < MAX; ++i) M[i] = 1LL*M[i-1]*(i+1)%MOD;
	for(int i=2; i < MAX; ++i) inv[i] = 1LL*(MOD-MOD/i)*inv[MOD%i]%MOD;
	scanf("%d", &t);
	while(t--){
		scanf("%d", &n);
		if(n < 5){
			printf("%d\n", n);
			continue;
		}
		k = lower_bound(K+1, K+MAX, n)-K;
		if(K[k] > n) k--;
		r = n - K[k];
		if(r == 0) ans = M[k];
		else if(r == k){
			ans = M[k+1];
			ans = 1LL * ans * inv[2] % MOD;
		}
		else if(r == k+1){
			ans = M[k];
			ans = 1LL * ans * inv[2] % MOD;
			ans = 1LL * ans * (k+3) % MOD;
		}
		else{
			ans = M[k+1];
			ans = 1LL * ans * inv[k+2-r] % MOD;
		}
		printf("%d\n", (ans+MOD)%MOD);
	}
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jpphy0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值