这道题乍一看非常简单,然而数据范围和时限直接劝退
其实还是很简单
考虑如何求a(i)逆元的和
这里需要用到一个前缀积s(i)
那么s(i)的逆元就是a(1)乘到a(i)的逆元
所以1/s(i-1)=1/s(i)*a(i)
1/a(i)=s(i-1)*1/s(i)
复杂度O(3n+logp)卡一卡可以过
Code:
1 #include<bits/stdc++.h> 2 #define int long long 3 #define N 5000010 4 using namespace std; 5 int n,p,k,tmp,ans; 6 int a[N],s[N],invs[N]; 7 /*--------卡常--------*/ 8 inline int rd(){ 9 int x=0; 10 char c=getchar(); 11 while(c<'0'||c>'9')c=getchar(); 12 while(c>='0'&&c<='9'){ 13 x=x*10+c-'0'; 14 c=getchar(); 15 } 16 return x; 17 } 18 inline void prt(int x){ 19 if(x>=10)prt(x/10); 20 putchar(x%10+'0'); 21 } 22 /*--------卡常--------*/ 23 inline int quickp(int a,int b){ 24 int ans=1; 25 while(b){ 26 if(b&1){ 27 ans=(ans*a)%p; 28 } 29 a=(a*a)%p; 30 b>>=1; 31 } 32 return ans; 33 } 34 signed main(){ 35 s[0]=1; 36 n=rd(),p=rd(),k=rd(); 37 //第一遍求前缀积 38 for(int i=1;i<=n;i++){ 39 a[i]=rd(); 40 s[i]=(s[i-1]*a[i])%p; 41 } 42 //预处理出来sn的逆元 43 invs[n+1]=quickp(s[n],p-2); 44 //第二遍倒着求前缀积的逆元 45 for(int i=n;i>=1;i--){ 46 invs[i]=(invs[i+1]*a[i])%p; 47 } 48 tmp=k; 49 //第三遍乘出答案 50 for(int i=1;i<=n;i++){ 51 ans=(ans+((invs[i+1]*s[i-1])%p*tmp)%p)%p; 52 tmp=(tmp*k)%p; 53 } 54 prt(ans); 55 return 0;//Perfect~ 56 }