VIjos 大整数(超级恶心的高精)

背景

很久很久以前,有个整数很大很囧

描述

一个k(1<=k<=80)位的十进制正整数N,就是所谓的大整数.
请你设计程序,对于给出的某一个大整数N,找到满足p^3+p^2+3p<=n的p的最大值.

格式

输入格式

输入数据只有一行,是一个K位的大整数N,行首行未无多余空格

输出格式

输出第一行为你所找到的P最大值,行首行末别乱加东西

样例1

样例输入1

1000000000000001000000000000003000000000000001

Copy

样例输出1

1000000000000000

  1 /*
  2     一道不错的高精练手题
  3     先确定p的位数
  4     然后从大到小找合适的p
  5     k最多80位
  6     p那最多 28位
  7     假设每一位都用0-9试一遍
  8     最多试不超过300遍
  9     即使加上高精复杂度也不会太高
 10 */
 11 #include<cstdio>
 12 #include<cstring>
 13 #include<iostream>
 14 #define MAXN 1010
 15
 16 using namespace std;
 17
 18 char s[MAXN];
 19
 20 int a[MAXN],b[MAXN],c[MAXN],e[MAXN],n[MAXN],_w;
 21
 22 inline bool judge() {
 23     if(e[0]<n[0]) return true;
 24     if(e[0]>n[0]) return false;
 25     for(int i=n[0];i>=1;i--) {
 26         if(e[i]>n[i]) return false;
 27         if(e[i]<n[i]) return true;
 28     }
 29     return true;
 30 }
 31
 32 inline void check() {
 33     for(int i=1;i<=a[0];i++) {
 34         if(a[i]<0) {
 35             a[i+1]--;
 36             a[i]+=10;
 37         }
 38     }
 39     while(a[0]>1&&!a[a[0]]) a[0]--;
 40     return;
 41 }
 42
 43 inline void _pluss() {
 44     a[_w]++;
 45     a[0]++;
 46     for(int i=1;i<=a[0];i++) {
 47         if(a[i]>=10) {
 48             a[i+1]++;
 49             a[i]-=10;
 50         }
 51     }
 52     while(a[0]>0&&!a[a[0]]) a[0]--;
 53     return;
 54 }
 55
 56 inline void __mul() {
 57     for(int i=0;i<=a[0];i++) b[i]=a[i];
 58     c[0]=a[0]+b[0]+1;
 59     for(int i=1;i<=a[0];i++)
 60       for(int j=1;j<=b[0];j++)
 61           c[i+j-1]+=a[i]*b[j];
 62     for(int i=1;i<=c[0];i++)
 63       if(c[i]>=10) {
 64           c[i+1]+=c[i]/10;
 65           c[i]%=10;
 66       }
 67     while(c[0]&&!c[c[0]]) c[0]--;
 68     for(int i=c[0];i>=0;i--) b[i]=c[i],c[i]=0;
 69     c[0]=a[0]+b[0]+1;
 70     for(int i=1;i<=a[0];i++)
 71       for(int j=1;j<=b[0];j++)
 72         c[i+j-1]+=a[i]*b[j];
 73     for(int i=1;i<=c[0];i++)
 74       if(c[i]>=10) {
 75         c[i+1]+=c[i]/10;
 76         c[i]%=10;
 77     }
 78     while(c[0]&&!c[c[0]]) c[0]--;
 79     e[0]=max(e[0],c[0])+1;
 80     for(int i=1;i<=e[0];i++) {
 81         e[i]+=c[i];
 82         if(e[i]>=10) {
 83             e[i+1]+=e[i]/10;
 84             e[i]%=10;
 85         }
 86     }
 87     while(e[0]&&!e[e[0]]) e[0]--;
 88     memset(c,0,sizeof c);
 89     memset(b,0,sizeof b);
 90 }
 91
 92 inline void _mul() {
 93     for(int i=0;i<=a[0];i++) b[i]=a[i];
 94     c[0]=a[0]*2+1;
 95     for(int i=1;i<=a[0];i++)
 96       for(int j=1;j<=b[0];j++)
 97           c[i+j-1]+=a[i]*b[j];
 98     for(int i=1;i<=c[0];i++)
 99       if(c[i]>=10) {
100           c[i+1]+=c[i]/10;
101           c[i]%=10;
102       }
103     while(c[0]&&!c[c[0]]) c[0]--;
104     e[0]=max(e[0],c[0])+1;
105     for(int i=1;i<=e[0];i++) {
106         e[i]+=c[i];
107         if(e[i]>=10) {
108             e[i+1]+=e[i]/10;
109             e[i]%=10;
110         }
111     }
112     while(e[0]&&!e[e[0]]) e[0]--;
113     memset(c,0,sizeof c);
114     memset(b,0,sizeof b);
115 }
116
117 inline void pluss() {
118     for(int i=1;i<=a[0];i++) b[i]=0;
119     b[0]=a[0]+1;
120     for(int i=1;i<=b[0];i++) {
121         b[i]+=3*a[i];
122         if(b[i]>=10) {
123             b[i+1]+=b[i]/10;
124             b[i]%=10;
125         }
126     }
127     while(b[0]&&!b[b[0]]) b[0]--;
128     e[0]++;
129     for(int i=1;i<=b[0];i++) {
130         e[i]+=b[i];
131         if(e[i]>=10) {
132             e[i+1]+=e[i]/10;
133             e[i]%=10;
134         }
135     }
136     while(e[0]&&!e[e[0]]) e[0]--;
137 }
138
139 int main() {
140     scanf("%s",s);
141     int len=strlen(s);
142     n[0]=len;
143     for(int i=1;i<=len;i++) n[i]=s[len-i]-48;
144     int _len=len/3+1;//因为有p^3
145     a[0]=_len;
146     a[_len]=0;
147     _w=_len;
148     while(true) {
149         if(!judge()) {
150             a[_w]--;
151             check();
152             _w--;
153             if(_w==0) break;
154             a[_w]=1;
155         }
156         else _pluss();
157         memset(e,0,sizeof e);
158         __mul();
159         _mul();
160         pluss();
161     }
162     for(int i=a[0];i>=1;i--) printf("%d",a[i]);
163     return 0;
164 } 

代码

				
时间: 2024-08-05 00:16:47

VIjos 大整数(超级恶心的高精)的相关文章

codevs 3119 高精度练习之大整数开根 (各种高精+压位)

/* codevs 3119 高精度练习之大整数开根 (各种高精+压位) 二分答案 然后高精判重 打了一个多小时..... 最后还超时了...压位就好了 测试点#1.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms 测试点#2.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms 测试点#3.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms 测试点#4.in 结果:AC 内存使用量: 256kB 时间使用量: 10ms 测试点#5.in 结果:AC 内

数楼梯——恶心的高精斐波那契数列

题目描述 楼梯有N阶,上楼可以一步上一阶,也可以一步上二阶. 编一个程序,计算共有多少种不同的走法. 输入输出格式 输入格式: 一个数字,楼梯数. 输出格式: 走的方式几种. 输入输出样例 输入样例#1: 4 输出样例#1: 5 说明 用递归会太慢,需用递推 (60% N<=50 ,100% N<=5000) 啊啊,数据太大了! 肿么办?! 当数据等于5000时的斐波那契数为 62763028004889570860352531083496840554785287027364574390258

vijos P1375 大整数(高精不熟的一定要做!)

/* 我尼玛这题不想说啥了 亏了高精写的熟..... 加减乘除max都写了 高精二分 */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 1010 #define memcpy(a,b); for(int i=0;i<=1000;i++)a[i]=b[i]; using namespace std; int n[maxn],len,l[maxn],r[maxn],mid[max

大整数因子(高精mod)

大整数的因子 总时间限制:  1000ms 内存限制:  65536kB 描述 已知正整数k满足2<=k<=9,现给出长度最大为30位的十进制非负整数c,求所有能整除c的k. 输入 一个非负整数c,c的位数<=30. 输出 若存在满足 c%k == 0 的k,从小到大输出所有这样的k,相邻两个数之间用单个空格隔开:若没有这样的k,则输出"none". 样例输入 30 样例输出 2 3 5 6 代码 高精模运算 #include<iostream> #inc

高精阶乘

求n!.当n很大的时候,会超出整数的范围. 这里用数组来进行高精阶乘.a[1]是个位,a[2]是十位......依次类推.每次要乘一个数的时候,就从个位(即a[1])开始乘这个数,>10的时候要%10再进位. 1 #include<cstdio> 2 #include<cstring> 3 const int N=100000; 4 5 int a[N]; 6 int i, j, n; 7 int t, pos/*位数*/, carry/*进位*/; 8 9 int main

大整数算法[13] 单数位乘法

★ 引子 最近在折腾 wxWidgets,同时拖延症又犯了,所以中断了好久.这次来讲讲单数位乘法,前面讲到 Comba 和 Karatsuba 乘法,这两个算法适合用来处理比较大的整数,但是对于一个大整数和一个单精度数相乘,其效果反而会不好,因为计算量过多.实际上单数位乘法只是基线乘法的一个特例,不存在嵌套循环进位,因此可以通过优化减少计算量.另外与完整的乘法不同的是,单数位乘法不需要什么临时变量存储和内存分配(目标精度增加除外). ★ 算法思路         单数位乘法类似于计算 12345

HDOJ1002-A + B Problem II(高精加)

Problem Description I have a very simple problem for you. Given two integers A and B, your job is to calculate the Sum of A + B. Input The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines fol

【日常学习】【区间DP+高精】codevs1166 矩阵取数游戏题解

题目来自NOIP2007TG3 如果在考场上我现在已经歇菜了吧 今天一整天的时间全部投在这道题上,收获不小. 先上题目 题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. 每次取走的各个元素只能是该元素所在行的行首或行尾: 3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素

高精除~~~

终于到高精除啦!!! 太令人开心了,我准备将高精除分为两个部分来讲 因为高精除中有高精除低精还有高精除高精 所以啊,这个先将高精除低精展现给大家 首先 因为是大整数除以小整数,所以我们运用的是按位相除法 做除法时,每一次的商都在0~9之内,每次求得的余数连接以后的若干位得到的新数被继续做除法. 因此在高精除法中还会涉及乘法和减法运算并且伴有移位处理. 为了简洁,运用0~9次循环减法取代商值. 好像可以直接上代码, 这个我找不到例题真是抱歉 #include<cstdio> #include&l