[luoguP1045] 麦森数(快速幂 + 高精度)
这道题纯粹是考数学。编程复杂度不大(别看我写了一百多行其实有些是可以不必写的)。
计算位数不必用高精时刻存,不然可想而知时间复杂度之大。首先大家要知道一个数学公式 logn(a*b)=logn(a)+logn(b)至于证明翻数学书吧。而且,用log10(n)+1即可求出n的位数。
则2^p的位数=log10(2^p)+1=p*log10(2)+1。这样,我们算的时候就不必随时存着位数了。
但是,如果直接写高精和n次循环,时间复杂度依旧很高。所以我们就要用快速幂。幂的运算是初中内容,几个公式如下:n^a*n^b=n^(a+b),(n^a)^b=n^(a*b)。
所以,我们就可以将乘方的复杂度优化成O(logn)了。
代码
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream> using namespace std; const int MAXN = 2001; char c[MAXN]; inline char *read()
{
scanf("%s", c);
return c;
} struct Big_int
{
int s[MAXN], idx;
Big_int()
{
idx = 0;
memset(s, 0, sizeof(s));
}
inline void operator = (char *c)
{
idx = strlen(c);
for(int i = 0; i < idx; i++) s[i] = c[idx - i - 1] - '0';
}
inline void operator = (int x)
{
idx = 0;
memset(s, 0, sizeof(s));
if(!x) idx++;
while(x)
{
s[idx] = x % 10;
x /= 10;
idx++;
}
}
inline void print()
{
if(!idx) printf("0");
else for(int i = idx - 1; i >= 0; i--)
{
if(!((i + 1) % 50)) puts("");
printf("%d", s[i]);
}
puts("");
}
}; inline Big_int operator + (const Big_int x, const Big_int y)
{
Big_int ret;
ret.idx = max(x.idx, y.idx) + 1;
for(int i = 0; i < ret.idx; i++)
{
ret.s[i] += x.s[i] + y.s[i];
if(ret.s[i] >= 10)
ret.s[i + 1] += 1, ret.s[i] -= 10;
}
while(!ret.s[ret.idx - 1] && ret.idx > 1) ret.idx--;
return ret;
} inline bool operator < (const Big_int x, const Big_int y)
{
if(x.idx < y.idx) return 1;
if(x.idx > y.idx) return 0;
for(int i = x.idx - 1; i >= 0; i--)
if(x.s[i] ^ y.s[i])
return x.s[i] < y.s[i];
return 0;
} inline Big_int operator - (Big_int x, Big_int y)
{
Big_int ret;
if(x < y) swap(x, y);
ret.idx = x.idx;
for(int i = 0; i < ret.idx; i++)
{
if(x.s[i] < y.s[i])
{
x.s[i] += 10;
x.s[i + 1]--;
}
ret.s[i] = x.s[i] - y.s[i];
}
while(!ret.s[ret.idx - 1] && ret.idx > 1) ret.idx--;
return ret;
} inline Big_int operator * (const Big_int x, const Big_int y)
{
Big_int ret;
ret.idx = x.idx + y.idx;
for(int i = 0; i < x.idx; i++)
for(int j = 0; j < y.idx; j++)
{
ret.s[i + j] += x.s[i] * y.s[j];
ret.s[i + j + 1] += ret.s[i + j] / 10;
ret.s[i + j] %= 10;
}
while(!ret.s[ret.idx - 1] && ret.idx > 1) ret.idx--;
return ret;
} int p;
Big_int a, ans; int main()
{
int i, j, k, x, y;
scanf("%d", &p);
cout << floor(log(2) / log(10) * p + 1);
ans = 1;
a = 2;
while(p)
{
if(p & 1) ans = ans * a, ans.idx = min(ans.idx, 500);
a = a * a, a.idx = min(a.idx, 500);
p >>= 1;
}
a = 1;
ans = ans - a;
ans.idx = 500;
ans.print();
return 0;
}
[luoguP1045] 麦森数(快速幂 + 高精度)的更多相关文章
- 洛谷试炼场-简单数学问题-P1045 麦森数-高精度快速幂
洛谷试炼场-简单数学问题 B--P1045 麦森数 Description 形如2^P−1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果PP是个素数,2^P-1 不一定也是素数.到19 ...
- [NOIP2003普及组]麦森数(快速幂+高精度)
[NOIP2003普及组]麦森数(快速幂+高精度) Description 形如2^P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2^P-1不一定也是素数.到1998 ...
- TZOJ 4839 麦森数(模拟快速幂)
描述 形如2^P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2^P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有9 ...
- 【高精度乘法】NOIP2003麦森数
题目描述 形如2^{P}-12P−1的素数称为麦森数,这时PP一定也是个素数.但反过来不一定,即如果PP是个素数,2^{P}-12P−1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的 ...
- NOIP200304麦森数
试题描述 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有9 ...
- 【转】[NOIP2003普及组]麦森数
来源:http://vivid.name/tech/mason.html 不得不纪念一下这道题,因为我今天一整天的时间都花到这道题上了.因为这道题,我学会了快速幂,学会了高精度乘高精度,学会了静态查错 ...
- vijosP1223麦森数
vijosP1223麦森数 链接:https://vijos.org/p/1223 [思路] 快速幂+高精乘. 计算2^p-1可以快速幂的方法在O(logn)的时间内出解,限于数据范围我们需要用到高精 ...
- 洛谷 P1045 麦森数
题目描述 形如2^{P}-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2^{P}-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=30213 ...
- 麦森数--NOIP2003
题目描述 形如2P−12^{P}-12P−1 的素数称为麦森数,这时PPP 一定也是个素数.但反过来不一定,即如果PPP 是个素数,2P−12^{P}-12P−1 不一定也是素数.到1998年底,人们 ...
随机推荐
- 暴力 hihoCoder 1178 计数
题目传送门 /* 暴力:这题真是醉了,直接暴力竟然就可以了!复杂度不会分析,不敢写暴力程序.. 枚举x,在不重复的情况下+ans,超过范围直接break */ #include <cstdio& ...
- synchronized(3)修饰语句块之:synchronized(一般对象)
synchronized(一般对象) 一次只有一个线程进入该代码块.此时,线程获得的是成员锁.例如: public class Thread7 { private Object xlock = new ...
- 转 ORA-12638: 身份证明检索失败
ORA-12638: 身份证明检索失败 的解决办法 2008年06月25日 星期三 11:42 the NTS option makes the Oracle client attempt to us ...
- YUM报错及解决办法
[root@xuegod60 ~]# yum clean all Loaded plugins: product-id, refresh-packagekit, security, subscript ...
- [转]C#委托Action、Action<T>、Func<T>、Predicate<T>
CLR环境中给我们内置了几个常用委托Action. Action<T>.Func<T>.Predicate<T>,一般我们要用到委托的时候,尽量不要自己再定义一 个 ...
- java jar文件打包成exe(Launch4j使用说明)
在日常的项目中需要把jar打包成exe.怎样快速的实现此功能.下面通过Launch4j的使用方法来介绍整个打包过程. 第一步:生成jar文件 第二部:使用Launch4j 图来描述过,简单明了.一切尽 ...
- 使用Jquery1.9 版本 来实现全选
在使用Jquery实现全选以及反选的时候, 使用attr()实现的时候,在浏览器第一次运行可以全选,但是第二次再全选,不管用. 通过查找资料,用 prop()方法代替attr()方法就行了. 注意: ...
- 微信小程序组件解读和分析:六、progress进度条
progress进度条组件说明: 进度条,就是表示事情当前完成到什么地步了,可以让用户视觉上感知事情的执行.progress进度条是微信小程序的组件,和HTML5的进度条progress类似. pro ...
- Objective - c Chapter 1 -2 Hello world
Objective - c Chapter 1 Hello world 1.1 1.2.On the Welcome screen, click "Create a new Xcode ...
- Farseer.net轻量级开源框架 中级篇:SQL执行报告
导航 目 录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 中级篇: 数据库切换 下一篇:Farseer.net轻量级开源框架 中级篇: 探究ORM(M ...