幂的末尾
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;
}
以上是关于幂的末尾的主要内容,如果未能解决你的问题,请参考以下文章
如何区分两个“onpause”事件 - 由单击“暂停”按钮引起,以及由到达媒体片段末尾引起?