你有一个大小为??的??????????,每次你可以从你已有的??????????中选择一个大小不为1的??????????,设他的大小为??,然后把它分裂成??和??−??,其中1≤??<??,这样你获得的收益是??∗(??−??)给定??,??,求最少分裂几次才能得到至少??的收益
思路:
首先需要证明
假设已经将题目中的S分成了n等份,那么对于当前分裂方式能够取得的最大收益需要满足:
当前假设S/n余数为0,或者尽可能接近均分
举例:
eg1. S=10 M=33
第一种方式:
所能够获得总收益为 come=5*5+2*3=31<33,若再将另外一个5分解才能满足>=33,此时分裂次数为3次
第二种方式:
此时总收益为 come=4*6+3*3=33 符合要求,分裂次数为2
对于第一种方式 (5,5)对于10是最优解,(2,3)对于5是最优解,但(2,3,5)对于10不是最优解
对于第二种方式(3,3)对于6是最优解,(4,6)对于10是最优解(再无法均分的情况下),同时(3,43,4)对于10是最优解,均分方式
eg2.假设最后分成了4份,如下:
则有:
总收益为:
则需保证(a1,a2)对于S1最优,(a3,a4)对于S2最优
那么(a1,a3),(a1,a4),(a2,a3),(a2,a4)也要保证最优,必有a1=a2=a3=a4=S/4(尽量平均分)
推论:对于总收益总能够表示为
发现 a1与其余每一项都有乘积形式
a2与其余每一项都有乘积形式
...
an与其余每一项都有乘积形式
这就要求尽可能将S均分给ai
解题思路:
枚举能够分成的份数从2到S,计算当前份数下能够获取的最大收益值与M比较,大于等于就跳出
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int main() { 4 int s,m; 5 scanf("%d %d",&s,&m); 6 for(int i=2;i<=s;++i) { 7 long long come=0;//总收益 8 long long sum=0;//由下往上的数字和 9 int ai=s/i; 10 int r=s%i; 11 if(r>=2) { 12 come=(ai+1)*(ai+1); 13 sum=(ai+1)*2; 14 } else if(r==1) { 15 come=(ai+1)*ai; 16 sum=ai*2+1; 17 } else { 18 come=ai*ai; 19 sum=ai*2; 20 } 21 int num; 22 for(int j=3;j<=i;++j) { 23 if(j<=r) num=ai+1; 24 else num=ai; 25 come+=num*sum; 26 sum+=num; 27 } 28 if(come>=m) { 29 printf("%d\n",i-1); 30 return 0; 31 } 32 } 33 printf("-1\n"); 34 return 0; 35 }
时间: 2024-10-11 18:18:37