幂的末尾

Posted zzctommy

tags:

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

毒瘤啊,2.5k

题目:求 (n^k) ,保留最后p位

(1le n le 10^{100},1le k,p le 10^5)

一看就是高精+快速幂。然而p的范围很大,所以普通高精度会炸,上FFT。结束。我不会压位/kk,本来写结构体是想压位的

#include<bits/stdc++.h>
using namespace std;
#define rint register int
const int N=400010;
struct Bigint {int len,num[N];}n;
int k,p;
int lim,lg,rev[N];
const double pi=acos(-1.0);
struct cp {
    double x,y;
    cp(){}
    cp(double _x,double _y):x(_x),y(_y){}
}A[N],B[N];
inline cp operator + (const cp &a,const cp &b) {
    return cp(a.x+b.x,a.y+b.y);
}
inline cp operator - (const cp &a,const cp &b) {
    return cp(a.x-b.x,a.y-b.y);
}
inline cp operator * (const cp &a,const cp &b) {
    return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
} 
inline void init(int n) {
    for(lim=1,lg=0;lim<=n;++lg,lim<<=1);
    for(rint i=0;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1));
}
inline void FFT(cp *a,int o) {
    for(rint i=0;i<lim;++i)if(i>rev[i])swap(a[i],a[rev[i]]);
    for(rint i=1;i<lim;i<<=1) {
        cp wn=cp(cos(pi/i),o*sin(pi/i));
        for(rint j=0;j<lim;j+=(i<<1)) {
            cp w0=cp(1,0);
            for(rint k=0;k<i;++k,w0=w0*wn) {
                cp X=a[j+k],Y=w0*a[i+j+k];
                a[j+k]=X+Y;
                a[i+j+k]=X-Y;
            }
        }
    }
}
inline void print(const Bigint& a) {
    for(rint i=0;i<a.len;++i)printf("%d",a.num[i]);
}
inline void mset(Bigint &a,int len=0) {
    a.len=len;
    for(rint i=0;i<=p;++i)a.num[i]=0;
}
inline Bigint read() {
    Bigint a;mset(a);
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))a.num[a.len++]=(ch^48),ch=getchar();
    return a;
}
Bigint operator * (Bigint a,Bigint b) {
    Bigint c;
    int len=a.len+b.len;
    init(len);c.len=lim;
    reverse(a.num,a.num+a.len);
    reverse(b.num,b.num+b.len);
    for(rint i=0;i<a.len;++i)A[i]=cp(a.num[i],0);for(rint i=a.len;i<lim;++i)A[i]=cp(0,0);
    for(rint i=0;i<b.len;++i)B[i]=cp(b.num[i],0);for(rint i=b.len;i<lim;++i)B[i]=cp(0,0);
    FFT(A,1),FFT(B,1);
    for(rint i=0;i<lim;++i)A[i]=A[i]*B[i];
    FFT(A,-1);
    mset(c,lim);
    for(rint i=0;i<=min(lim-1,p);++i) {
        c.num[i]+=round(A[i].x/lim);
        if(c.num[i]>=10)c.num[i+1]+=c.num[i]/10,c.num[i]%=10;
    }
    while((!c.num[c.len-1]&&c.len>1)||c.len>p)--c.len;
    reverse(c.num,c.num+c.len);
    return c;
}
Bigint operator ^ (Bigint a,int k) {
	Bigint res;
	mset(res);
	res.len=1,res.num[0]=1;
	while(k) {
		if(k&1)res=res*a;
		a=a*a;
		k>>=1;
	}
	return res;
}
Bigint a,b;
signed main() {
	n=read();scanf("%d%d",&k,&p);
	n=n^k;
	print(n);
    return 0;
}

以上是关于幂的末尾的主要内容,如果未能解决你的问题,请参考以下文章

K尾相等数

如何区分两个“onpause”事件 - 由单击“暂停”按钮引起,以及由到达媒体片段末尾引起?

css常用代码片段 (更新中)

带有神秘附加字符的 Javascript Date getTime() 代码片段

求幂的 SIMD 代码

如何从片段外部清除/重置地图?