码迷,mamicode.com
首页 > 其他好文 > 详细

幂的末尾

时间:2020-04-07 12:23:47      阅读:63      评论:0      收藏:0      [点我收藏+]

标签:class   就是   +=   signed   getc   void   opera   lin   pac   

毒瘤啊,2.5k

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

\(1\le n \le 10^{100},1\le 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;
}

幂的末尾

标签:class   就是   +=   signed   getc   void   opera   lin   pac   

原文地址:https://www.cnblogs.com/zzctommy/p/12628852.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!