高精度开方
2017-04-22 12:00
211 查看
什么辣鸡高精度开方
二分
code
竖式开方
普通版
code
加强版
code
有点意思
恐怖
OI渣渣参不了GDKOI,唉
写写高精度开方,都是码农(不码农怎么消磨时间呢…)
以下的是开整数方,想看开小数的绕道
方法应该不少,这是其中的两种
时间复杂度O(log2n)
二分法改改能算小数嘚,不过很恶心
明显,O(log2n)还不慢
数据太大还卡不死你
接着就到了interesting的竖式开方算法
鬼魅的东西……
照图,竖式两位两位算,已经很清楚了,不多说
数据大忒爽,毕竟这方法两位两位开,二分渣渣
时间复杂度?
大约O(5log10n)吧……(实际少一点)比二分快了很多
恩,想算小数,只需在尾部不断落下两个0即可(改起来舒服多了)
我也不信上面的东西是纯手打的,吐……这很™码农
只是把中间那个
现在,时间复杂度就变成了
O(log210×log10n2)≈O(32log10n)
加上各种奇奇怪怪的高精度除法(中间二分去掉)
不算高精度的时间,就是O(log10n2)……
二分
code
竖式开方
普通版
code
加强版
code
有点意思
恐怖
什么辣鸡高精度开方?
闲的无 (dan) 聊 (teng)OI渣渣参不了GDKOI,唉
写写高精度开方,都是码农(不码农怎么消磨时间呢…)
以下的是开整数方,想看开小数的绕道
方法应该不少,这是其中的两种
二分
二分,不必多说时间复杂度O(log2n)
二分法改改能算小数嘚,不过很恶心
code
var n,l,r,mid:ansistring; function add(s1,s2:ansistring):ansistring; var a,b,c:array[0..10000]of longint; n,i,l1,l2,l3,x:longint; s:string; begin fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0); fillchar(c,sizeof(c),0); x:=0; l1:=length(s1); for i:=1 to l1 do a[l1-i+1]:=ord(s1[i])-ord('0'); l2:=length(s2); for i:=1 to l2 do b[l2-i+1]:=ord(s2[i])-ord('0'); i:=1; while (i<=l1)or(i<=l2) do begin c[i]:=a[i]+b[i]+x; x:=c[i] div 10; c[i]:=c[i] mod 10; inc(i); end; if x>0 then begin l3:=i; c[i]:=x; end else l3:=i-1; add:=''; for i:=l3 downto 1 do add:=add+chr(c[i]+48); end; function time(n1,n2:ansistring):ansistring; var a,b,c:array[0..10000]of longint; lena,lenb,lenc,i,j,x:longint; begin fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0); fillchar(c,sizeof(c),0); lena:=length(n1); lenb:=length(n2); for i:=1 to lena do a[lena-i+1]:=ord(n1[i])-ord('0'); for i:=1 to lenb do b[lenb-i+1]:=ord(n2[i])-ord('0'); for i:=1 to lena do begin x:=0; for j:=1 to lenb do begin c[i+j-1]:=a[i]*b[j]+x+c[i+j-1]; x:=c[i+j-1]div 10; c[i+j-1]:=c[i+j-1]mod 10; end; c[i+j]:=x; end; lenc:=lena+lenb; while (c[lenc]=0)and(lenc>1)do dec(lenc); time:=''; for i:=lenc downto 1 do time:=time+chr(c[i]+48); end; function division(s:ansistring;y:int64):ansistring; var a,b,c:array[0..10000]of longint; lena,lenb,lenc,i,j,x:longint; begin fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0); fillchar(c,sizeof(c),0); lena:=length(s); for i:=1 to lena do a[lena-i+1]:=ord(s[i])-ord('0'); x:=0; for i:=lena downto 1 do begin x:=x*10+a[i]; c[i]:=x div y; x:=x mod y; end; lenc:=lena; division:=''; while (c[lenc]=0)and(lenc>1)do dec(lenc); for i:=lenc downto 1 do division:=division+chr(c[i]+48); end; function bigger(s1,s2:ansistring):boolean; begin if (length(s1)>length(s2))or(length(s1)=length(s2))and((s1>s2))then exit(true) else exit(false); end; function smaller(s1,s2:ansistring):boolean; begin if (length(s1)<length(s2))or(length(s1)=length(s2))and((s1<=s2))then exit(true) else exit(false); end; function judge(s:ansistring):boolean; begin if smaller(time(s,s),n) and bigger(time(add(s,'1'),add(s,'1')),n)then exit(true) else exit(false); end; begin readln(n); l:='1'; r:=n; mid:=division(add(l,r),2); while true do begin if judge(mid) then begin writeln(mid); halt; end; if bigger(time(mid,mid),n)then begin r:=mid; mid:=division(add(l,r),2); end else if smaller(time(mid,mid),n)then begin l:=add(mid,'1'); mid:=division(add(l,r),2); end; end; end.
明显,O(log2n)还不慢
数据太大还卡不死你
接着就到了interesting的竖式开方算法
竖式开方
普通版
(图来自百度)鬼魅的东西……
照图,竖式两位两位算,已经很清楚了,不多说
数据大忒爽,毕竟这方法两位两位开,二分渣渣
时间复杂度?
大约O(5log10n)吧……(实际少一点)比二分快了很多
恩,想算小数,只需在尾部不断落下两个0即可(改起来舒服多了)
code
var a:array[0..1000]of string; s,ans,t1,t2,t3,x,y:string; n,i,j,len,z:longint; function add(s1,s2:ansistring):ansistring; var a,b,c:array[0..10000]of longint; n,i,l1,l2,l3,x:longint; s:string; begin fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0); fillchar(c,sizeof(c),0); x:=0; l1:=length(s1); for i:=1 to l1 do a[l1-i+1]:=ord(s1[i])-ord('0'); l2:=length(s2); for i:=1 to l2 do b[l2-i+1]:=ord(s2[i])-ord('0'); i:=1; while (i<=l1)or(i<=l2) do begin c[i]:=a[i]+b[i]+x; x:=c[i] div 10; c[i]:=c[i] mod 10; inc(i); end; if x>0 then begin l3:=i; c[i]:=x; end else l3:=i-1; add:=''; for i:=l3 downto 1 do add:=add+chr(c[i]+48); end; function minus(s1,s2:ansistring):ansistring; var a,b,c:array[0..10000]of longint; i,l1,l2,l3:longint; z:ansistring; begin fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0); fillchar(c,sizeof(c),0); if s1=s2 then exit('0'); l1:=length(s1); l2:=length(s2); if (l1<l2)or(l1=l2)and(s1<s2)then begin z:=s1; s1:=s2; s2:=z; end; l1:=length(s1); l2:=length(s2); for i:=1 to l1 do a[l1-i+1]:=ord(s1[i])-ord('0'); for i:=1 to l2 do b[l2-i+1]:=ord(s2[i])-ord('0'); i:=1; while i<=l1 do begin if a[i]<b[i] then begin a[i]:=a[i]+10; a[i+1]:=a[i+1]-1; end; c[i]:=a[i]-b[i]; inc(i); end; l3:=i; while (c[l3]=0) do dec(l3); minus:=''; for i:=l3 downto 1 do minus:=minus+chr(c[i]+48); end; function time(n1,n2:ansistring):ansistring; var a,b,c:array[0..10000]of longint; lena,lenb,lenc,i,j,x:longint; begin fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0); fillchar(c,sizeof(c),0); lena:=length(n1); lenb:=length(n2); for i:=1 to lena do a[lena-i+1]:=ord(n1[i])-ord('0'); for i:=1 to lenb do b[lenb-i+1]:=ord(n2[i])-ord('0'); for i:=1 to lena do begin x:=0; for j:=1 to lenb do begin c[i+j-1]:=a[i]*b[j]+x+c[i+j-1]; x:=c[i+j-1]div 10; c[i+j-1]:=c[i+j-1]mod 10; end; c[i+j]:=x; end; lenc:=lena+lenb; while (c[lenc]=0)and(lenc>1)do dec(lenc); time:=''; for i:=lenc downto 1 do time:=time+chr(c[i]+48); end; function bigger(s1,s2:ansistring):boolean; begin if (length(s1)>length(s2))or(length(s1)=length(s2))and((s1>s2))then exit(true) else exit(false); end; function smaller(s1,s2:ansistring):boolean; begin if (length(s1)<length(s2))or(length(s1)=length(s2))and((s1<=s2))then exit(true) else exit(false); end; begin readln(s); len:=length(s); if len mod 2=0 then begin len:=len div 2; for i:=1 to len do a[i]:=copy(s,2*i-1,2); end else begin len:=len div 2+1; a[1]:=s[1]; for i:=2 to len do a[i]:=copy(s,2*i-2,2); end; x:='0'; ans:='0'; for i:=1 to len do begin val(a[i],z); str(z,a[i]); x:=add(time(x,'100'),a[i]); for j:=0 to 9 do begin str(j,t1); str(j+1,t2); if j<>9 then begin t3:=time(add(time(ans,'20'),t1),t1); if smaller(t3,x) and bigger(time(add(time(ans,'20'),t2),t2),x)then begin if ans='0' then ans:=''; ans:=ans+chr(j+48); x:=minus(x,t3); break; end end else begin t3:=time(add(time(ans,'20'),t1),t1); if ans='0' then ans:=''; ans:=ans+'9'; x:=minus(x,t3); end; end; end; writeln(ans); end.
我也不信上面的东西是纯手打的,吐……这很™码农
加强版
其实没什么加强的只是把中间那个
for j:=0 to 9 do循环变成了二分罢了(思路还是竖式开方)
现在,时间复杂度就变成了
O(log210×log10n2)≈O(32log10n)
code
var a:array[0..10000]of string; s,ans,t,x,y,l,r,mid:string; n,i,j,len,z:longint; function add(s1,s2:ansistring):ansistring; var a,b,c:array[0..10000]of longint; n,i,l1,l2,l3,x:longint; s:string; begin fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0); fillchar(c,sizeof(c),0); x:=0; l1:=length(s1); for i:=1 to l1 do a[l1-i+1]:=ord(s1[i])-ord('0'); l2:=length(s2); for i:=1 to l2 do b[l2-i+1]:=ord(s2[i])-ord('0'); i:=1; while (i<=l1)or(i<=l2) do begin c[i]:=a[i]+b[i]+x; x:=c[i] div 10; c[i]:=c[i] mod 10; inc(i); end; if x>0 then begin l3:=i; c[i]:=x; end else l3:=i-1; add:=''; for i:=l3 downto 1 do add:=add+chr(c[i]+48); end; function minus(s1,s2:ansistring):ansistring; var a,b,c:array[0..10000]of longint; i,l1,l2,l3:longint; z:ansistring; begin fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0); fillchar(c,sizeof(c),0); if s1=s2 then exit('0'); l1:=length(s1); l2:=length(s2); if (l1<l2)or(l1=l2)and(s1<s2)then begin z:=s1; s1:=s2; s2:=z; end; l1:=length(s1); l2:=length(s2); for i:=1 to l1 do a[l1-i+1]:=ord(s1[i])-ord('0'); for i:=1 to l2 do b[l2-i+1]:=ord(s2[i])-ord('0'); i:=1; while i<=l1 do begin if a[i]<b[i] then begin a[i]:=a[i]+10; a[i+1]:=a[i+1]-1; end; c[i]:=a[i]-b[i]; inc(i); end; l3:=i; while (c[l3]=0) do dec(l3); minus:=''; for i:=l3 downto 1 do minus:=minus+chr(c[i]+48); end; function time(n1,n2:ansistring):ansistring; var a,b,c:array[0..10000]of longint; lena,lenb,lenc,i,j,x:longint; begin fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0); fillchar(c,sizeof(c),0); lena:=length(n1); lenb:=length(n2); for i:=1 to lena do a[lena-i+1]:=ord(n1[i])-ord('0'); for i:=1 to lenb do b[lenb-i+1]:=ord(n2[i])-ord('0'); for i:=1 to lena do begin x:=0; for j:=1 to lenb do begin c[i+j-1]:=a[i]*b[j]+x+c[i+j-1]; x:=c[i+j-1]div 10; c[i+j-1]:=c[i+j-1]mod 10; end; c[i+j]:=x; end; lenc:=lena+lenb; while (c[lenc]=0)and(lenc>1)do dec(lenc); time:=''; for i:=lenc downto 1 do time:=time+chr(c[i]+48); end; function division(s:ansistring;y:longint):ansistring; var a,b,c:array[0..10000]of longint; lena,lenb,lenc,i,j,x:longint; begin fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0); fillchar(c,sizeof(c),0); lena:=length(s); for i:=1 to lena do a[lena-i+1]:=ord(s[i])-ord('0'); x:=0; for i:=lena downto 1 do begin x:=x*10+a[i]; c[i]:=x div y; x:=x mod y; end; lenc:=lena; division:=''; while (c[lenc]=0)and(lenc>1)do dec(lenc); for i:=lenc downto 1 do division:=division+chr(c[i]+48); end; function bigger(s1,s2:ansistring):boolean; begin if (length(s1)>length(s2))or(length(s1)=length(s2))and((s1>s2))then exit(true) else exit(false); end; function smaller(s1,s2:ansistring):boolean; begin if (length(s1)<length(s2))or(length(s1)=length(s2))and((s1<=s2))then exit(true) else exit(false); end; begin readln(s); len:=length(s); if len mod 2=0 then begin len:=len div 2; for i:=1 to len do a[i]:=copy(s,2*i-1,2); end else begin len:=len div 2+1; a[1]:=s[1]; for i:=2 to len do a[i]:=copy(s,2*i-2,2); end; x:='0'; ans:='0'; for i:=1 to len do begin val(a[i],z); str(z,a[i]); x:=add(time(x,'100'),a[i]); l:='0'; r:='9'; while true do begin mid:=division(add(l,r),2); t:=time(add(time(ans,'20'),mid),mid); if smaller(t,x) and bigger(time(add(time(ans,'20'),add(mid,'1')),add(mid,'1')),x)then begin if ans='0' then ans:=''; ans:=ans+mid; x:=minus(x,t); break; end else begin if smaller(t,x) then l:=add(mid,'1') else r:=minus(mid,'1'); end; end; end; writeln(ans); end.
有点意思
哦对了,这个竖式开方算法应该还可以降时间加上各种奇奇怪怪的高精度除法(中间二分去掉)
不算高精度的时间,就是O(log10n2)……
恐怖……
相关文章推荐
- 高精度模板2(带符号压位加减乘除开方封包)
- 高精度模板(带符号的加减乘除开方/压位)
- Project Euler Problem 80-高精度开方-牛顿逼近法
- [高精度模板][Pascal]整数加、减、乘、除、开方等
- SGU111 高精度开方
- 高精度开方数
- 牛顿迭代法求高精度开方
- sgu111高精度开方
- PREV-34 矩阵翻硬币 (高精度开方,相乘)
- POJ2109 高精度(含大数开方)+二分
- 高精度开方
- [置顶] Project Euler Problem 80-高精度开方-牛顿逼近法
- 【转】看起来很神奇的高精度开方
- UVA 10023 Square root(高精度开方)
- 牛顿迭代法求高精度开方
- Dollar Days POJ 3181 完全背包+高精度
- 高精度运算 51 nod 大数相乘
- 针对windows系统的高精度定时器
- 高精度之高精度加减法
- |BZOJ 1655|无限背包|高精度|[Usaco2006 Jan] Dollar Dayz 奶牛商店