今天又是考试,然而早晨7:30考到中午12:30,没时间吃饭了。
然而并不会做题啊啊啊。
T1:
系数显然是组合数啊......
然后,模数不是质数?这不是拓展lucas裸题吗?
等等,拓展lucas,我只写过一遍诶......
看我大力出奇迹:
就是把模数先分解成p1^k1*p2^k2...的形式,然后我们在mod px^kx的情况下进行计算,最后再用互质的CRT合并即可。
mod px^kx的情况下怎么算?我们能把与px互质的阶乘计算出来,再单独计算阶乘中有px的多少次方。
然后互质的直接在mod px^kx下求逆元即可,非互质的直接次数加减。
然而考场上被卡常只有90......
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define debug cout 6 typedef long long int lli; 7 using namespace std; 8 const int maxn=4e5+1e2; 9 10 lli in[maxn],ans; 11 lli c[maxn],modc[maxn]; 12 lli fac[maxn],tim[maxn]; 13 lli dvs[maxn],tms[maxn],pows[maxn]; 14 int n,mod,now,psnow,cnt; 15 16 inline lli fastpow(lli base,lli tim,lli mod) { 17 lli ret = 1; 18 while(tim) { 19 if( tim & 1 ) ret = ret * base % mod; 20 if( tim >>= 1 ) base = base * base % mod; 21 } 22 return ret; 23 } 24 inline lli exgcd(lli a,lli b,lli& x,lli& y) { 25 if( !b ) return x = 1 , y = 0 , a; 26 lli ret = exgcd(b,a%b,y,x); 27 y -= a / b * x; 28 return ret; 29 } 30 inline lli inv(lli t,lli mod) { 31 static lli x,y; 32 exgcd(t,mod,x,y); 33 return ( x % mod + mod ) % mod; 34 } 35 inline void getcoprime(int x,int& retc,int& rett) { 36 retc = x , rett = 0; 37 while( ! ( retc % now ) ) retc /= now , ++rett; 38 } 39 inline void preseq() { 40 fac[0] = 1 , tim[0] = 0; 41 for(int i=1,c,t;i<=n;i++) { 42 getcoprime(i,c,t); 43 fac[i] = fac[i-1] * c % psnow , tim[i] = tim[i-1] + t; 44 } 45 } 46 inline void getdvs(int x) { 47 for(int i=2;(lli)i*i<=x;i++) 48 if( ! ( x % i ) ) { 49 dvs[++cnt] = i , pows[cnt] = 1; 50 while( ! ( x % i ) ) ++tms[cnt] , pows[cnt] *= i , x /= i; 51 } 52 if( x != 1 ) dvs[++cnt] = x , pows[cnt] = x , tms[cnt] = 1; 53 } 54 inline void cnow(int x,int& retc,int& rett) { 55 retc = fac[n-1] * inv(fac[x],psnow) % psnow * inv(fac[n-1-x],psnow) % psnow; 56 rett = tim[n-1] - tim[x] - tim[n-1-x]; 57 } 58 inline void merge(int x,int fac,int tim) { 59 lli cur = (lli) fac * fastpow(now,tim,mod) % mod; 60 c[x] = ( c[x] + cur * ( mod / psnow ) % mod * inv( mod / psnow , psnow ) % mod ) % mod; 61 } 62 63 64 int main() { 65 scanf("%d%d",&n,&mod); 66 for(int i=1;i<=n;i++) scanf("%lld",in+i); 67 getdvs(mod); 68 for(int i=1;i<=cnt;i++) { 69 now = dvs[i] , psnow = pows[i] , preseq(); 70 for(int j=0,c,t;j<n;j++) cnow(j,c,t) , merge(j,c,t); 71 } 72 for(int i=1;i<=n;i++) ( ans += in[i] * c[i-1] % mod ) %= mod; 73 printf("%lld\n",ans); 74 return 0; 75 }