Part 1 推导

题目描述经过我们精简,可以发现实际上是要我们求一个序列:

2 ^ 0 + 2 ^ 1 + 2 ^ 2 + 2 ^ 3 + ... + 2 ^ {63} = \sum_{i=0}^{63}

学过MO的同学看到这个式子应该很熟悉,我下面列举两种解法:

等比数列求和

等比数列求和公式证明如下:

等比数列公式证明

本题中q = 2,带入等比数列求和公式得到:

S = 2 ^ {64} - 1

加上首项

q = 2的等比数列有一个特性(所以频频被考)。如果我们将原式加上2 ^ 0,可以得到如下结果:

2 ^ 0 + 2 ^ 0 = 2 ^ 1

2 ^ 1 + 2 ^ 1 = 2 ^ 2

2 ^ 2 + 2 ^ 2 = 2 ^ 3

...

2 ^ {63} + 2 ^ {63} = 2 ^ {64}

S = 2 ^ {64} - 1

可以看到与等比数列求和所得结果一模一样

Part 2 代码

Python

python内置了**用来求幂运算,如下代码可以求上方那个式子:

  1. 2 ** 64 - 1

结果为18446744073709551615,你会发现这怎么和标准答案不一样呢?其实是std是对答案进行了四舍五入。

手动舍入print(18446744073709552000)

正解:

  1. def intRound(x, y):
  2. if ((x // (y // 10)) % 10) > 4:
  3. return (x // y + 1) * y
  4. else:
  5. return x // y * y
  6. print(intRound(2 ** 64 - 1, 1000))

C++

__int128 O(n)

C++ 中可以使用pow来计算幂,但是2 ^ 64 - 1太大了,无法使用long long来存(long long极限为2 ^ 63 - 1),也不能使用pow。
一种方案是用_int128来存。

  1. #include <cstdio>
  2. using namespace std;
  3. void _print(__int128 x) {
  4. if (x > 9) {
  5. _print(x / 10);
  6. }
  7. putchar(x % 10 + '0');
  8. }
  9. __int128 round(__int128 x, int y) {
  10. if (((x / (y / 10)) % 10) > 4) {
  11. return (x / y + 1) * y;
  12. } else {
  13. return x / y * y;
  14. }
  15. }
  16. int main()
  17. {
  18. __int128 ans = 1;
  19. for (int i = 0; i < 64; i++) { // 手动求 2 ^ 64
  20. ans *= 2;
  21. }
  22. ans -= 1; // 进行 -1
  23. _print(round(ans, 1000)); // 取整后输出
  24. }

scanf、printf、cin、cout均不支持__int128,这里参考了C++ __int128的使用这篇文章。

ull O(1)

比赛中是不能用__int128的。
诶,既然long long存不下,那么unsigned long long能不能存的下呢?
通过查表发现,unsigned long long的最大值:18446744073709551615
这个数字正好是本题的答案。

在头文件climits中记载了所有数据类型的最大值最小值。

  1. #include <iostream>
  2. #include <climits>
  3. using namespace std;
  4. unsigned long long round(unsigned long long x, int y) {
  5. if (((x / (y / 10)) % 10) > 4) {
  6. return (x / y + 1);
  7. } else {
  8. return x / y * y;
  9. }
  10. }
  11. int main()
  12. {
  13. cout << round(ULLONG_MAX, 1000) << "000";
  14. }

由于此题不四舍五入之前为ull的最大值,舍入后会溢出,需要手动加几个0。


如果谁能写一个更好看的round函数请在评论区中发出来:D。

参考:

  1. C++ __int128的使用
  2. 妈咪叔的latexlive编辑器
点赞(0)
 

9.1 分

6 人评分

 

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 3 条评论

dotcpp0693251 1年前 回复TA
@int 无语,自己答案都是错的来考大家,标准答案就是2^64-1,谁出的题出来谢罪
int 2年前 回复TA
@int 新手写法,乱过的
int 2年前 回复TA
#include <bits/stdc++.h>
using namespace std;

int main()
{
	unsigned long long sum=0,n=1;
	for(int i=0;i<64;i++){
		sum+=n;
		n*=2;
	}
	cout<<sum<<endl;
}