openjudge4.6贪心算法——407:Heritage

家庭财产分割问题中,使用递推方法确定每个亲戚的遗产比例,确保教堂份额最大化,涉及大整数处理技巧。
摘要由CSDN通过智能技术生成

题目

407:Heritage
描述
Your rich uncle died recently, and the heritage needs to be divided among your relatives and the church (your uncle insisted in his will that the church must get something). There are N relatives (N <= 18) that were mentioned in the will. They are sorted in descending order according to their importance (the first one is the most important). Since you are the computer scientist in the family, your relatives asked you to help them. They need help, because there are some blanks in the will left to be filled. Here is how the will looks:

Relative #1 will get 1 / … of the whole heritage,
Relative #2 will get 1 / … of the whole heritage,
---------------------- …
Relative #n will get 1 / … of the whole heritage.

The logical desire of the relatives is to fill the blanks in such way that the uncle’s will is preserved (i.e the fractions are non-ascending and the church gets something) and the amount of heritage left for the church is minimized.
输入
The only line of input contains the single integer N (1 <= N <= 18).
输出
Output the numbers that the blanks need to be filled (on separate lines), so that the heritage left for the church is minimized.
样例输入
2
样例输出
2
3

翻译

各种读,还是不太理解。
大概意思是有遗产,分给家人,还要有一部分给教堂。不是平均分配,要从头到尾倒序分配,先多后少。后来找到题解后,才知道
Relative #1 will get 1 / … of the whole heritage,
很重要。填空是填到这个省略号的地方。可能跟the heritage needs to be divided among your relatives and the church有关,divided也许不能仅仅理解为分配!

理解

第一个人分1/2(拿走1/2,剩1/2)
第二个人分1/3(2*(2-1)+1,是不是理解为从剩的1/2拿走2/3=1/3,剩1/6)
第三个人分1/7(3*(3-1)+1,是不是理解为从剩的1/6拿走2/3=1/9,剩1/6/3=1/12,但是这个结果跟答案不一样,推测错误)
第四个人分1/43(7*(7-1)+1,后面的推测没得到验证)
第i个人分1/(i*(i-1)+1)。
这样问题就是递推,第一个人分2,第二个人分3,第三个人分7,第i个人分i*(i-1)+1,就算这个就行了。
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
到18时得有100005位
问题的难点就是长整数计算。

问题

(i*(i-1)+1)
希望有能力的朋友能讲下为什么一定是d[i+1]=d[i]*(d[i]-1)+1。非常感谢

代码

#include <bits/stdc++.h>
using namespace std;
int n;
string d[20]={“0”,“2”,“3”};
void view(){
for(int i=1;i<=n;i++)cout<<d[i]<<endl;
}
string suan(string a,string b){
int m=b.length()-1;
while(b[m]==‘0’&&m>=0){//如果尾数是零,全改成9
b[m–]=‘9’;
}
if(m>=0)b[m]=(b[m]-‘1’)+‘0’;//直到不是零,减去1
int d[100005];//结果存整型数组,长度没仔细研究,200位都会错
memset(d,0,sizeof(d));
int dm=0;
string c=“”;
for(int i=a.length()-1;i>=0;i–)//被乘数和乘数都是从个位开始计算,从最右边往左边
for(int j=b.length()-1;j>=0;j–){
int ad=a[i]-‘0’,bd=b[j]-‘0’,
ix=a.length()-1-i,jx=b.length()-1-j;//跟被乘数位置是相反的,个位计算在0位,往高位可以延展
d[ix+jx]+=adbd;//被乘数和乘数位数的和是乘积的位数
dm=max(dm,i+j);//记住长度
}
d[0]+=1;//d[i+1]=d[i]
(d[i]-1)+1,完成+1部分
for(int i=0;d[i]>0||i<=dm;i++){//遍历每一位,个位在零位最左边
if(d[i]>9)d[i+1]+=d[i]/10,d[i]%=10;//如果>9进位
c=char(d[i]+‘0’)+c;//结果存到字符串中,高位在左边
if(i>dm)dm++;//长度可以不变
}
return c;
}
int main(){
//freopen(“in.cpp”,“r”,stdin);
cin>>n;
for(int i=3;i<=n;i++)
d[i]=suan(d[i-1],d[i-1]);
//d[i]=d[i-1]*(d[i-1]-1)+1;
view();
return 0;
}

总结

大整数乘法多做几遍就熟练了,就是需要坐得住,仔细考虑并解决各个环节。
尤其是被乘数乘数个位在右边高位,但是计算结果个位在左边低位0位,是挺有意思的。
还得要提高英语阅读理解能力,同样的单词,读不到真意思。

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值