乘法逆元2題解
阿新 • • 發佈:2020-06-29
這是一篇題解類似物
提交記錄記錄了我的非酋歷程
乘法逆元× 憑臉過題√
傳送
我們首先看到這個東西
妙哇
對每個數都求一次逆元肯定是會被卡的,我們來看看要輸出的東西有什麼優雅的性質
我們不妨先暴力通分一下
原式=
\[ \frac{1}{a_1a_2.....a_n} \sum_{i=1}^{n}\frac{k^ia_1a_2...a_n}{a_i} \]
設\(a_1a_2...a_n=M\),則原式=
\[ \frac{1}{M} \sum_{i=1}^n \frac{k^iM}{a_i} \]
考慮到\(\frac{M}{a_i}\)還要求逆元,所以我們求字首積和字尾積。用字首積和字尾積來表示\(\frac{M}{a_i}\)
最後只用對\(M\)求逆元。因為這裡保證\(p\)是質數,所以費馬小定理適用
然鵝這題卡常,所以我們需要用毒瘤卡常技巧
一些技巧
1.少開\(int\)
2.用\(inline\)
3.實測(+p)%p比%p要快
程式碼如下(過不了就去試試討好評測姬叭)
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<vector> #define pa pair<int,int> using namespace std; typedef long long ll; const double eps=1e-13; inline int read(){ char ch=getchar(); int x=0;bool f=0; while(ch<'0'||ch>'9') { if(ch=='-') f=1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); } return f?-x:x; } int n,p,k,a[5000009],M; ll ji[2][5000009],kk=1,fz;//1 qz,0 hz int ksm(ll a,int b){ ll rtn=1; while(b){ if(b&1) rtn=(rtn*a)%p; a=(a*a)%p; b>>=1; } return rtn; } int main(){ n=read();p=read();k=read();ji[1][0]=1;ji[0][n+1]=1; for(register int i=1;i<=n;++i) a[i]=read(),ji[1][i]=(ji[1][i-1]*a[i]+p)%p;//inv[i]==inv[i%p]??? for(register int i=n;i>=1;--i) ji[0][i]=(ji[0][i+1]*a[i]+p)%p; for(register int i=1;i<=n;++i){ kk=(kk*k+p)%p; fz=(fz+kk*ji[1][i-1]%p*ji[0][i+1]+p)%p; } M=(ksm(ji[1][n],p-2)); fz=(fz*M+p)%p; printf("%d\n",fz); }