【模板篇】数论大杂烩~
離省選已經不剩幾天了, 然而自己還是啥也不會, 所以就臨陣磨槍刷一刷板子, 萬一用上了就賺到了~~
這一篇就寫寫數論?(希望只考到自己打的板子然而這是不可能的←_←
盡量不壓行吧, 能寫得好懂點就寫得好懂一點吧... (為了省事就全開long long了哈, 卡常題請謹慎復制...)
里面枚舉的內容可能沒啥規(guī)律, 想起啥寫啥, 應該會很亂...
先是應該是不用寫的gcd:
LL gcd(LL a,LL b){if(!b) return a;return gcd(b,a%b); }然后是exgcd:
void exgcd(LL a,LL b,LL &x,LL &y){if(!b) x=1,y=0;else exgcd(b,a%b,y,x),y-=(a/b)*x; }快速冪也是炒雞常用的:
LL qpow(LL a,LL b,LL p,LL s=1){for(;b;b>>=1,a=a*a%p)if(b&1) s=s*a%p;return s; }然后是跟質數或者辣雞反演有關的題里幾乎都要用到的線篩(這玩意我還日常打不對的說...)
篩質數的同時寫一下篩\(\mu, \varphi, \sigma_0,\sigma_1\)這些函數(打表找規(guī)律的積性函數就不寫了也寫不完)
Emmmm寫個線篩寫了好久最后果然還是出錯了..
逆元相關:
然后是兩種求\(a\)在\(mod\ p\)逆元的方法:
線性求出所有逆元:
inv[1]=1; for(int i=2;i<p;++i)inv[i]=(p-(p/i))*inv[p%i]%p;O(1)快速乘(損精度):
LL multi(Ll a,LL b){return (a*b-(LL)((long double)a*b/p)*p+p)%p; }然后是一發(fā)Lucas定理:
// 這里默認階乘和階乘逆元已經預處理好分別放在fac和inv數組里了~ LL lucas(LL n,LL m,LL p){if(n<m) return 0;if(n<p) return fac[x]*inv[y]*inv[x-y];return lucas(n/p,m/p,p)*lucas(n%p,m%p,p); }再來一波CRT(中國剩余定理)
//假設模數存在p數組里, 余數存在c數組里, 一共有n個式子, 模數的總乘積是P. void CRT(LL ans=0){for(int i=0;i<n;++i)ans=(ans+c[i]*(P/p[i])%P*inv(P/p[i],p[i])%P)%P;return ans; }突然發(fā)現自己還沒寫過擴展CRT哇, 趕緊新寫一發(fā)~
int exCRT(){for(int i=2;i<=n;++i){p1=p[i-1],p2=p[i],c1=c[i-1],c2=c[i];g=gcd(p1,p2);if((c2-c1)%g) return -1;p[i]=p1*p2/t;c[i]=inv(p1/t,p2/t)*((c2-c1)/t)%(p2/t)*p1+c1;c[i]=(c[i]%p[i]+p[i])%p[i];}return c[n]; }然后寫一發(fā)bsgs~叫拔山蓋世的都是邪教!北上廣深才是王道!
map<LL,int> mmp; LL BSGS(LL y,LL z,LL p){ mmp.clear();LL m=sqrt(p)+1; po=qpow(y,m,p);for(LL j=0;j<=m;++j){v[z]=j; z=z*y%c;} z=1;for(LL i=1;i<=m;++i){z=z*po%p;if(v[x]) return i*m-v[x];}return -1; }然后就是組合數題的boss了(僅代表個人觀點), 非常神的 擴展Lucas~~~~
去年這時候學的, 現在幾乎忘得一干二凈
剛才打了一遍板子, 然而還是沒有背過...
再來補充一些反演相關:
最基本的枚舉除法
公式就記這幾個其他常見的都可以推...
\[ \mu*1=\epsilon \\ \varphi*1=n \\ id_k*1=\sigma_k \]
套路性的東西:
\[ \sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=1]=\sum_{d=1}^n\mu(d)\left\lfloor\frac nd\right\rfloor\left\lfloor\frac md\right\rfloor \\ \sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)=1]=2*\sum_{d=1}^n\varphi(d)-1 \]
杜教篩的模板(舒老師說這玩意卵用沒有但我覺得很有用噠(肯定是我太弱了)):
\[ 要求出f(x)的前綴和s_f(x), 我們要找到一個合適的函數g(x), 滿足g(x)和(f*g)(x)的前綴和都易求(一般是要求O(1)). \\ 令s_{f*g}(x)表示(f*g)x的前綴和, 那么有: \\ s_f(x)=\frac{s_{f*g}(x)-\sum_{i=2}^ns_f(\left\lfloor\frac ni\right\rfloor)g(i)}{g(1)} (當然正常來說g(1)=1就不用除辣)\\ 然后我們枚舉除法對上式整除分塊遞歸處理s_f(\left\lfloor\frac ni\right\rfloor)這個部分就可以了~ \]
于是附上幾個常見的易求前綴和的函數的求和公式:
\[ \sum_{i=1}^n1(i)=n \\ \sum_{i=1}^n\epsilon(i)=1 \\ \sum_{i=1}^nid(i)=\frac{n(n+1)}2 \\ \sum_{i=1}^nid_2(i)=\frac{n(n+1)(2n+1)}6 \\ \sum_{i=1}^nid_3(i)=(\frac{n(n+1)}2)^2 \]
然后就是一些注意事項:
- \(10^{10}\)范圍杜教篩篩\(O(n^\frac 23)\)大約是\(4.7*10^6\), 所以500W一般可以, 不過空間允許的話再篩大一點在1e7左右會更好~
- \(10^{10}*{10^9+7}\)有幾率會爆long long, 雖然情況比較少但我相信足夠毒瘤的出題人是可以有足夠的時間和耐心搞出來hack數據的..., 所以保險起見要開unsigned long long...
- long long計算非常慢, 能用int的地方盡量用int, 當然那就要注意強轉long long步步取模(少一個都有可能炸←_←)的問題了~
- 枚舉因子的時候最好把設\(i=td\)寫出來防止把應該化的\(t\)丟掉(可以適當找下規(guī)律驗證化的式子對否)..
- 大約就這樣吧, 說太多自己也是記不住的...
轉載于:https://www.cnblogs.com/enzymii/p/8697113.html
總結
以上是生活随笔為你收集整理的【模板篇】数论大杂烩~的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 删除表空间联带数据文件
- 下一篇: 『Numpy』内存分析_高级切片和内存数