zoukankan      html  css  js  c++  java
  • [2019.3.4]BZOJ1213 [HNOI2004]高精度开根

    首先你需要一个python高精度模板。

    然后二分答案,快速幂判断就好了。

    设被开根数(n)(b)位。

    发现朴素的高精度乘法是(O(b^2))的,所以我们考虑优化

    你可以写压位高精(我最后的做法,压了8位),或者写一个FFT。

    提示:最好不要尝试同时压8位+FFT,否则你就会像我一样因为精度问题调一晚上+一下午并且最终放弃QWQ

    有一个小优化,由于一个(b)位数开(m)次根的位数不会超过(lfloorfrac{b}{m} floor+1),所以二分上界可以设为(lfloorfrac{b}{m} floor+1)个9,在(m)比较大的时候得到比较好的优化效果。

    加优化时间复杂度(O((frac{b}{m})^2log10^{frac{b}{m}}log m))

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const long long base=1e9;
    int la,lb,s,lc;
    struct NUM{
    	long long v[2000];
    	int sz;
    	void operator~(){
    		memset(v,0,sizeof(v));
    	}
    	NUM operator+(const NUM&y)const{
    		NUM tmp;
    		~tmp;
    		long long w=0;
    		tmp.sz=max(sz,y.sz);
    		for(int i=1;i<=tmp.sz;++i)tmp.v[i]=v[i]+y.v[i]+w,w=tmp.v[i]/base,tmp.v[i]%=base,w&&i==tmp.sz?++tmp.sz:0;
    		return tmp;
    	}
    	NUM operator*(const NUM&y)const{
    		NUM tmp;
    		~tmp;
    		long long w=0;
    		tmp.sz=sz+y.sz;
    		for(int i=1;i<=sz;++i)for(int j=1;j<=y.sz;++j)tmp.v[i+j-1]+=v[i]*y.v[j];
    		for(int i=1;i<=tmp.sz;++i)tmp.v[i]+=w,w=tmp.v[i]/base,tmp.v[i]%=base,w&&i==tmp.sz?++tmp.sz:0;
    		while(!tmp.v[tmp.sz])--tmp.sz;
    		return tmp;
    	}
    	NUM operator/(const int&y){
    		NUM tmp;
    		~tmp;
    		long long w=0;
    		if(v[sz]>=y)tmp.sz=sz;
    		else w=v[sz]*base,tmp.sz=sz-1;
    		for(int i=tmp.sz;i>=1;--i)w+=v[i],tmp.v[i]=w/y,w=w%y*base;
    		return tmp;
    	}
    	NUM operator-(const int&y){
    		NUM tmp;
    		~tmp;
    		tmp.sz=sz;
    		for(int i=1;i<=sz;++i)tmp.v[i]=v[i];
    		tmp.v[1]-=y;
    		int nw=1;
    		while(tmp.v[nw]<0)tmp.v[nw]+=base,--tmp.v[++nw];
    		if(tmp.sz!=0&&!tmp.v[tmp.sz])--tmp.sz;
    		return tmp;
    	}
    	NUM operator+(const int&y){
    		NUM tmp;
    		~tmp;
    		tmp.sz=sz;
    		for(int i=1;i<=sz;++i)tmp.v[i]=v[i];
    		tmp.v[1]+=y;
    		int nw=1;
    		while(tmp.v[nw]>=base)tmp.v[nw]-=base,++tmp.v[++nw];
    		if(tmp.v[tmp.sz+1])++tmp.sz;
    		return tmp;
    	}
    	bool operator>(const NUM&y)const{
    		if(sz!=y.sz)return sz>y.sz;
    		for(int i=sz;i>=1;--i)if(v[i]!=y.v[i])return v[i]>y.v[i];
    		return false;
    	}
    	bool operator<(const NUM&y)const{
    		if(sz!=y.sz)return sz<y.sz;
    		for(int i=sz;i>=1;--i)if(v[i]!=y.v[i])return v[i]<y.v[i];
    		return false;
    	}
    }N,L,R,MID;
    int n,m,nw,bs;
    char tmp[10010];
    void scan(NUM &x){
    	scanf("%s",tmp+1);
    	n=strlen(tmp+1),nw=n+1;
    	while(nw>1){
    		++x.sz,bs=1;
    		while(nw>1&&bs<base)x.v[x.sz]+=(tmp[--nw]-'0')*bs,bs*=10;
    	}
    }
    void print(NUM x){
    	if(!x.sz)putchar('0');
    	else{
    		for(int i=x.sz,p0=base/10;i>=1;--i,p0=base/10){
    			if(i!=x.sz)while(x.v[i]<p0)putchar('0'),p0/=10;
    			if(p0)printf("%d",x.v[i]);
    		}
    	}
    }
    NUM POW(NUM x,int y){
    	NUM tot;
    	tot.sz=tot.v[1]=1;
    	while(y)y&1?tot=tot*x,0:0,x=x*x,y>>=1;
    	return tot;
    }
    int tt=0;
    int main(){
    	scanf("%d",&m);
    	scan(N);
    	L.sz=0,n=n/m+1,nw=0;
    	while(nw<n){
    		++R.sz,bs=1;
    		while(nw<n&&bs<base)R.v[R.sz]+=9*bs,bs*=10,++nw;
    	}
    	while(L<R){
    		MID=(L+R+1)/2;
    		if(POW(MID,m)>N)R=MID-1;
    		else L=MID;
    	}
    	print(L);
    	return 0;
    }
    
  • 相关阅读:
    CodeForces 734F Anton and School
    CodeForces 733F Drivers Dissatisfaction
    CodeForces 733C Epidemic in Monstropolis
    ZOJ 3498 Javabeans
    ZOJ 3497 Mistwald
    ZOJ 3495 Lego Bricks
    CodeForces 732F Tourist Reform
    CodeForces 732E Sockets
    CodeForces 731E Funny Game
    CodeForces 731D 80-th Level Archeology
  • 原文地址:https://www.cnblogs.com/xryjr233/p/BZOJ1213.html
Copyright © 2011-2022 走看看