题解 P5431 【【模板】乘法逆元2】

Great_Influence

2019-05-31 17:32:13

Solution

简单套路。 如果直接做,则复杂度为 $O(n\log p)$ ,不可能通过。 因此我们考虑优化。 可以先回忆阶乘的逆元是怎么算的。 我们计算阶乘的逆元的时候,是先求一个前缀积,然后求出最后一个前缀积的逆元后,一个个乘回去就可以得到每个阶乘的逆元了。 这个可以也这样处理。我们求出前缀积后,直接一个个乘回去就可以了。注意我们处理出的是每个前缀积的逆元,因此每个逆元再乘上上一个前缀积就可以得到这一个数字的逆元了。 用代码来说就是: $$prd[i]=prd[i-1]*a[i]$$ $$inv[n]=inv(prd[n])$$ $$inv[k]=inv[k+1]*a[k]$$ $$realinv[k]=inv[k]*prd[k-1]$$ 复杂度 $O(n+\log p)$ 。 注意这道题实际上并不需要将逆元存起来。我们只需要将数组翻转,然后在倒着乘回去的时候顺便计算答案就可以了。你也可以将前缀积改成后缀积。 代码: ```cpp #include<cctype> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<iostream> #define Rep(i,a,b) for(register int i=(a);i<=(b);++i) #define Repe(i,a,b) for(register int i=(a);i>=(b);--i) #define rep(i,a,b) for(register int i=(a);i<(b);++i) #define pb push_back #define mp make_pair typedef unsigned long long uint64; typedef unsigned int uint32; typedef long long ll; using namespace std; namespace IO { const uint32 Buffsize=1<<15,Output=1<<23; static char Ch[Buffsize],*S=Ch,*T=Ch; inline char getc() { return((S==T)&&(T=(S=Ch)+fread(Ch,1,Buffsize,stdin),S==T)?0:*S++); } static char Out[Output],*nowps=Out; inline void flush(){fwrite(Out,1,nowps-Out,stdout);nowps=Out;} template<typename T>inline void read(T&x) { x=0;static char ch;T f=1; for(ch=getc();!isdigit(ch);ch=getc())if(ch=='-')f=-1; for(;isdigit(ch);ch=getc())x=x*10+(ch^48); x*=f; } template<typename T>inline void write(T x,char ch='\n') { if(!x)*nowps++='0'; if(x<0)*nowps++='-',x=-x; static uint32 sta[111],tp; for(tp=0;x;x/=10)sta[++tp]=x%10; for(;tp;*nowps++=sta[tp--]^48); *nowps++=ch; } } using IO::read; using IO::write; using IO::getc; using IO::flush; inline void Chkmin(int&u,int v){u>v?u=v:0;} inline void Chkmax(int&u,int v){u<v?u=v:0;} inline void file() { #ifndef ONLINE_JUDGE freopen("water.in","r",stdin); freopen("water.out","w",stdout); #endif } const int MAXN=5e6+7; static int n,mod,k,a[MAXN]; inline void init() { read(n),read(mod),read(k); Rep(i,1,n)read(a[i]); } static int sfd[MAXN]; inline int power(int u,int v) { register int sm=1; for(;v;v>>=1,u=(ll)u*u%mod)if(v&1) sm=(ll)sm*u%mod; return sm; } inline void solve() { sfd[n+1]=1; Repe(i,n,1)sfd[i]=(ll)sfd[i+1]*a[i]%mod; register int iv=power(sfd[1],mod-2),pwk=1,ans=0; Rep(i,1,n) { pwk=(ll)pwk*k%mod; ans=(ans+(ll)pwk*iv%mod*sfd[i+1])%mod; iv=(ll)iv*a[i]%mod; } cout<<ans<<endl; } int main() { file(); init(); solve(); return 0; } ```