高精度开根
作者:互联网
输入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