特殊问题 用两位long long 代替大数运算
来源:互联网 发布:java 重写 重载 编辑:程序博客网 时间:2024/05/10 16:10
特殊问题 用两位long long 代替大数运算
原问题
矩阵取数【问题描述】
帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均
为非负整数。游戏规则如下:
1. 每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有元素;
2. 每次取走的各个元素只能是该元素所在行的行首或行尾;
3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素值*2i,
其中i 表示第i 次取数(从1 开始编号);
4. 游戏结束总得分为m次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分
需要解决的大数运算
每次取一个数
X(0≤X≤1000)
总得分为 前面累积的得分+X∗2i (1≤i≤80)
每次得分范围为 不超过1000∗280 即≤1028
最多取80次计算最后得分的范围为 答案≤1030
思路
用 long long a[2] 存放 表示已经积累的分数
用 long long b[2] 存放 上次的2i
用 long long c[2] 存放这次的 分数
计算
- 1.算出此次得分
b[1]=b[1]*2;b[0]=b[0]*2;if(b[0]>Limit){ b[1]++; //这里进位只可能是1 b[0]%=Limit;}//b[2] 等于这次的2^ic[1]=b[1]*x;c[0]=b[0]*x;if(c[0]>Limit){ c[1]+=c[0]/Limit; //这里进位有可能大于1 c[0]%=Limit; }//乘上x
- 1.加到总得分
a[1]+=c[1];a[0]+=c[0];if(a[0]>limit){ a[1]++; //这里进位只可能是1 a[0]=a[0]%Limit;}
常数LImit应该为多少
64位的a[1] 可以设定a[1]范围为
0≤a[1]≤1019
至于a[0] 假设0≤a[0]≤10i
我们需要19+i≥30 (两个long long 能表示的范围要符合题目需要)
并且10i∗1000≤1019 (确保最坏情况不溢出)
所以11≤i≤16
至于Limit 应该取10i
代码
/*【问题描述】帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均为非负整数。游戏规则如下:1. 每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有元素;2. 每次取走的各个元素只能是该元素所在行的行首或行尾;3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素值*2i,其中i 表示第i 次取数(从1 开始编号);4. 游戏结束总得分为m次取数得分之和。帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。输入描述 Input Description第1行为两个用空格隔开的整数n和m。第2~n+1 行为n*m矩阵,其中每行有m个用单个空格隔开的非负整数。输出描述 Output Description输出 仅包含1 行,为一个整数,即输入矩阵取数后的最大得分。*/#include<cstdio>#include<iostream>#include<string.h>#include<string>#include<cmath>#pragma warning(disable:4996)using namespace std;class bign{public: long long high; long long low; friend ostream& operator<<(ostream& out, bign &a) { if (a.high) { out << a.high; printf("%06d", a.low / 1000000); printf("%06d", a.low % 1000000); } else { cout << a.low; } return out; }};int n, m;int matrix[81][81];bign dp[81][81][81];bign two[81]; //存2^ilong long Limit = 1000000000000;//10^12bign add(bign a, bign b){ a.high += b.high; a.low += b.low; if (a.low > Limit) { a.high++; a.low %= Limit; } return a;}bign mul(bign a, int b)//b<=1000{ a.high *= b; a.low *= b; if (a.low > Limit) { a.high += a.low / Limit; a.low %= Limit; } return a;}bool ismax(bign a, bign b){ if (a.high > b.high || (a.high == b.high&& a.low > b.low))return 1; return 0;}int main(){ //n行m列 cin >> n >> m; int i, j; for (i = 1; i <= n; i++) { for (j = 1; j <= m; j++) { cin >> matrix[i][j]; } } memset(dp, 0, sizeof(dp)); two[1].high = 0; two[1].low = 2; for (i = 2; i <= m; i++) //计算2^i { two[i] = mul(two[i - 1], 2); //cout << two[i] << endl; } for (i = 1; i <= n; i++) //计算每一行 { int head; for (head = m; head >=1; head--) { int end; for (end = head; end <=m; end++) { int NumberOfTimes = m-(end - head + 1)+1; if (head == end) { dp[i][head][end] = mul(two[NumberOfTimes], matrix[i][head]); } else { bign a = add(dp[i][head + 1][end],mul(two[NumberOfTimes],matrix[i][head])); bign b = add(dp[i][head][end - 1], mul(two[NumberOfTimes], matrix[i][end])); dp[i][head][end] = ismax(a, b) ? a : b; } } } } bign sum = bign{ 0,0 }; for (i = 1; i <= n; i++)//累加每一行 { sum = add(sum, dp[i][1][m]); } cout << sum; return 0;}
0 0
- 特殊问题 用两位long long 代替大数运算
- A+B超过long long 大数相加问题
- long long 表示问题
- Hibernate.String/LONG 代替
- Hibernate.String/LONG 代替
- VC++编译器中用_int64代替long long
- Java 处理大数运算,超过int long 之类的
- 大数数字读法 unsigned long long
- Long和long的问题
- unsigned long long的问题
- Long
- int ,long ,long long
- long long,long,int
- int、long、long long
- unsigned long的问题
- 【long long与int 的模运算速度比较】
- int,long int, unsigned int,unsigned long int,long long的表示范围问题(转)
- int 与 long 、long long
- [Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优
- iOS学习总结之导航控制器
- Tools 命名空间的使用与 Support Library Annotations 介绍
- 动态添加行,删除行
- 安卓中简单的线性布局
- 特殊问题 用两位long long 代替大数运算
- map/reduce
- Android 常用控件
- 忙是治疗一切神经病的良药
- Java开发中的23种设计模式详解
- 1098. Insertion or Heap Sort (25) / 1089. Insert or Merge (25)
- 修改Android actionbar 溢出菜单按钮(OverflowButton)默认图标
- ping
- U-boot的bootargs环境变量详解