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

Posted 心之所向 素履以往

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VIjos 大整数(超级恶心的高精)相关的知识,希望对你有一定的参考价值。

背景

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

描述

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

格式

输入格式

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

输出格式

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

样例1

样例输入1

1000000000000001000000000000003000000000000001

样例输出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 } 
代码

 



以上是关于VIjos 大整数(超级恶心的高精)的主要内容,如果未能解决你的问题,请参考以下文章

高精度Vijos P1010 清帝之惑之乾隆

一些恶心的代码片段

vijos p1526——超级汉诺塔

二分高精度Vijos P1472 教主的集合序列

caioj1450:快速傅里叶变换大整数乘法

大整数乘法(高精度乘法)