NOIP2003 普及组 [麦森数] C++

NOIP2003 普及组 麦森数

题目描述

形如 2 P − 1 2^{P}-1 2P1 的素数称为麦森数,这时 P P P 一定也是个素数。但反过来不一定,即如果 P P P 是个素数, 2 P − 1 2^{P}-1 2P1 不一定也是素数。到 1998 年底,人们已找到了 37 个麦森数。最大的一个是 P = 3021377 P=3021377 P=3021377,它有 909526 位。麦森数有许多重要应用,它与完全数密切相关。

任务:输入 P ( 1000 < P < 3100000 ) P(1000<P<3100000) P(1000<P<3100000),计算 2 P − 1 2^{P}-1 2P1 的位数和最后 500 500 500 位数字(用十进制高精度数表示)

输入格式

文件中只包含一个整数 P ( 1000 < P < 3100000 ) P(1000<P<3100000) P(1000<P<3100000)

输出格式

第一行:十进制高精度数 2 P − 1 2^{P}-1 2P1 的位数。

2 ∼ 11 2\sim 11 211 行:十进制高精度数 2 P − 1 2^{P}-1 2P1 的最后 500 500 500 位数字。(每行输出 50 50 50 位,共输出 10 10 10 行,不足 500 500 500 位时高位补 0 0 0

不必验证 2 P − 1 2^{P}-1 2P1 P P P 是否为素数。

样例 #1

样例输入 #1

1279

样例输出 #1

386
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000104079321946643990819252403273640855
38615262247266704805319112350403608059673360298012
23944173232418484242161395428100779138356624832346
49081399066056773207629241295093892203457731833496
61583550472959420547689811211693677147548478866962
50138443826029173234888531116082853841658502825560
46662248318909188018470682222031405210266984354887
32958028878050869736186900714720710555703168729087

提示

【题目来源】

NOIP 2003 普及组第四题

解题思路

  • 十进制位数公示
  • 高精度 * 高精度
  • 快速幂

在这里插入图片描述

AC代码

/**
 * @problem: P1045 [NOIP2003 普及组] 麦森数
 * @link: https://www.luogu.com.cn/problem/P1045
 * @category: math 高精度
 * @date:
 * @Author: YaeSaraki
 **/

#include <algorithm>
#include <iostream>
#include <vector>
#include <ranges>
#include <cmath>

#define ALL(v) v.begin(), v.end()
#define DBG(x) std::cout << #x << " = " << (x) << '\n'
//#define int long long

using ll = long long;
using PI = std::pair<int, int>;

std::vector<int> sub(std::vector<int> &a, std::vector<int> &b) {
	/* A >= B */
	int t = 0;
	std::vector<int> c;
	for (int i = 0; i < a.size(); ++i) {
		t = a[i] - t;
		if (i < b.size()) t -= b[i];
		c.push_back((t + 10) % 10);
		if (t < 0) t = 1;
		else t = 0;
	}
	while (c.size() > 1 && c.back() == 0) c.pop_back();
	return c;
}

/** 高精度 * 高精度 */
std::vector<int> mul(std::vector<int> &a, std::vector<int> &b) {
	int t = 0;
	std::vector<int> c(500);
	/* 丢弃高于501位的数 */
	for (int i = 0; i < std::min((int)a.size(), 500); ++i) {
		for (int j = 0; j < std::min((int)b.size(), 500); ++j) {
			if (i + j < 500) c[i + j] += a[i] * b[j];
		}
	}
	/* 进位处理 */
	for (int i = 0; i < c.size(); ++i) {
		if (c[i] > 9) {
			c[i + 1] += c[i] / 10;
			c[i] %= 10;
		}
	}

	while (c.size() > 1 && c.back() == 0) c.pop_back();
	return c;
}

/** 快速幂 */
std::vector<int> qPow(std::vector<int> &a, int n) {
	std::vector<int> ans = {1};
	while (n) {
		if (n & 1) ans = mul(ans, a);
		a = mul(a, a);
		n >>= 1;
	}
	return ans;
}

inline void solve() {
	int n; std::cin >> n;
	std::vector<int> a = {2};
	/* 快速幂求2 ^ n */
	a = qPow(a, n);

	/* 减去1 */
	std::vector<int> b = {1};
	a = sub(a, b);

	/* 输出位数 */
	std::cout << (int)(log10(2) * n) + 1 << '\n';

	/* 处理答案位数 */
	while (a.size() != 500) {
		while (a.size() > 500) a.pop_back();
		while (a.size() < 500) a.push_back(0);
	}
	
	/* 输出 */
	for (int i = 499; ~i; --i) {
		std::cout << a[i];
		/* 注意50一行 */
		if (i % 50 == 0) std::cout << "\n";
	}
}

bool rt = false;
signed main() {
  std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout.tie(nullptr);
#ifndef ONLINE_JUDGE
  freopen("test.in", "r", stdin);
#endif
  if (rt) { int T; std::cin >> T; while (T--) solve(); }
  else solve();
  return (0 ^ 0);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值