其他分享
首页 > 其他分享> > 高精度开根

高精度开根

作者:互联网

输入n,m

求m开n次方根

#include<bits/stdc++.h>
typedef long long ll;
const int K=3,N=40003/K,M=pow(10,K),p=998244353,g=3,gi=332748118;
int m,i,l,r,L,lim,re[N],f[11],a[N],b[N],inv;
char s[10003];
struct NUM{
    int t,a[N];
}x,A;
inline int pls(int x,int y){x+=y;return x>=p?x-p:x;}
inline int dec(int x,int y){x-=y;return x<0?x+p:x;}
inline int mul(int x,int y){return (ll)x*y%p;}
inline int pow(int x,int y){
    int ans=1;
    for (;y;y>>=1,x=mul(x,x))
        if (y&1) ans=mul(ans,x);
    return ans;
}
inline void ntt(int *A,int opt){
    for (int i=0;i<lim;i++)
        if (i<re[i]) A[i]^=A[re[i]],A[re[i]]^=A[i],A[i]^=A[re[i]];
    int pp=p-1>>1;
    for (int mid=1;mid<lim;mid<<=1,pp>>=1){
        int wn=pow((opt==1)?g:gi,pp);
        for (int R=mid<<1,j=0;j<lim;j+=R){
            int w=1;
            for (int k=0;k<mid;k++,w=mul(w,wn)){
                int x=A[j+k],y=mul(w,A[j+(k|mid)]);
                A[j+k]=pls(x,y);
                A[j+(k|mid)]=dec(x,y);
            }
        }
    }
    if (opt==-1)
        for (int i=0;i<lim;i++) a[i]=mul(a[i],inv);
}
inline NUM mul(NUM x,NUM y,int t1,int t2){
    for (int i=0;i<x.t-t1;i++) a[i]=x.a[i+t1];
    for (int i=0;i<y.t-t2;i++) b[i]=y.a[i+t2];
    lim=1;L=0;
    for (;lim<x.t+y.t-t1-t2;lim<<=1,L++);
    for (int i=0;i<lim;i++) re[i]=(re[i>>1]>>1)|((i&1)<<(L-1));
    for (int i=x.t-t1;i<lim;i++) a[i]=0;
    for (int i=y.t-t2;i<lim;i++) b[i]=0;
    inv=pow(lim,p-2);
    ntt(a,1);ntt(b,1);
    for (int i=0;i<lim;i++) a[i]=mul(a[i],b[i]);
    ntt(a,-1);x.t+=y.t;
    for (int i=0;i<=t1+t2;i++) x.a[i]=0;
    for (int i=t1+t2;i<x.t;i++) x.a[i]+=a[i-t1-t2],x.a[i+1]=x.a[i]/M,x.a[i]%=M;
    while (x.t && !x.a[x.t-1]) x.t--;
    return x;
}
inline NUM pow(NUM x,int y,int t1){
    NUM z;
    int t2=0;
    if (t1<0) t1=0;
    z.t=z.a[0]=1;
    for (;y;y>>=1,x=mul(x,x,t1,t1),t1<<=1)
        if (y&1) z=mul(z,x,t2,t1),t2+=t1;
    return z;
}
inline bool operator >=(NUM x,NUM y){
    if (x.t!=y.t) return x.t>y.t;
    for (int i=x.t-1;i>=0;i--)
        if (x.a[i]!=y.a[i]) return x.a[i]>y.a[i];
    return 1;
}
inline void print(NUM x){
    for (int i=x.t-1;i>=0;i--){
        if (i<x.t-1){
            int k=(int)log10(x.a[i])+1;
            if (!x.a[i]) k=0;
            for (int j=0;j<K-k;j++) putchar('0');
        }
        if (x.a[i]) printf("%d",x.a[i]);
    }
}
int main(){
    scanf("%d\n",&m);
    gets(s);
    f[0]=1;
    for (i=1;i<9;i++) f[i]=f[i-1]*10;
    A.t=strlen(s);
    if (A.t==1 && s[0]=='0'){
        putchar('0');
        return 0;
    }
    for (i=A.t-1;i>=0;i--) A.a[(A.t-1-i)/K]+=(s[i]^48)*f[(A.t-1-i)%K];
    A.t=((A.t-1)/K)+1;
    x.t=(A.t-1)/m+1;
    for (i=x.t-1;i>=0;i--){
        l=0;r=M-1;
        while (l<r){
            x.a[i]=l+r+1>>1;
            if (A>=pow(x,m,i)) l=x.a[i];
            else r=x.a[i]-1;
        }
        x.a[i]=l;
    }
    print(x);
}

 

标签:return,高精度,int,pow,NUM,ans,inline,开根
来源: https://blog.csdn.net/queen00000/article/details/90295760