板子
***A.数学***
1.组合数的函数(快速幂)
```cpp
int q_pow(int x,int n)
{
int res=1;
while(n)
{
if(n&1)
{
res=res*x%mod;
}
x=x*x%mod;
n>>=1;
}
return res;
}
int C(int n,int m)
{
if(m>n)return 0;
return (fac[n] * q_pow(fac[m], mod - 2) % mod * q_pow(fac[n - m], mod - 2) % mod)%mod ;
}
fac[0]=1;
fac[n]=fac[n-1]*n%mod;
```

2.素数筛
```cpp
bool s[100015];
void solve()
{
s[1]=1;
for(int i=2;i*i<=100005;i++)
{
if(!s[i])
{
for(int j=i*i;j<=100005;j+=i)s[j]=1;
}
}
}
```
3.快速乘(会爆long long时,不写高精度的方法)
```cpp
ll mul(ll a,ll b){
ll ans=0;
while(b){
if(b&1) ans=(ans+a)%mod;
a=a*2%mod;
b>>=1;
}
return ans;
}
```
4.拓展欧几里得 (求ax+by=gcd(a,b)的解 /求逆元)
```cpp
int exGcd(int a,int b,int &d,int &x,int &y)
{
if(!b) { d=a;x=1;y=0; }
else { gcd(b,a%b,d,y,x); y-= x*(a/b); }
}
```
求逆元:A和MOD互质的时候才存在,否则不存在逆元
> 首先同余模定理如下:
>
> (a+b)%c=(a%c+b%c)%c;
>
> (a*b)%c=(a%c*b%c)%c;
>
> 也就是说对于取模的加减法,和乘法我们都可以运用同余模定理来进行计算,那么,对于除法我们应该怎么办呢?首先想到的就是把除法转换成乘法,然后就可以运用定理了。怎么转换呢,在普通乘法中,我们知道,除以一个数就等于乘上一个数的倒数,其实这个倒数就是我们所谓的逆元。A*(A的逆元)=单位元。在普通的乘法中
> A的逆元就是它的倒数。
> 那么,在模n乘法中,我们应该怎么求逆元呢?我们设A的逆元为X,那么我们就可以得到(A*X)%MOD=1(模n乘法的单位元也是1)。对这个式子进行变形
> ,就可以得到:
> (A*X)%MOD=1;那么肯定存在k使得
>
> A*X=k*MOD+1;
>
> 移项可得:A*X-k*MOD=1;
>
> 所以,当A和MOD互素时,就可以写成
>
> A*X-k*MOD=gcd(A,MOD);
>
> 如果把A看做a,MOD看做b,X看做x,-k看做y的话,则上式可化为:
>
> ax+by=gcd(a,b);
>
> 这样就可以用扩展欧几里得算法求出来x了,也就是我们要找的逆元。
***B.数据结构***
1.链表
```cpp
queue<int> q;//先假定线性队列,弹出最顶部值,根据要求插入队尾
q.pop();
if(必要なら)q.insert(x);
```
2.st表
```cpp
int arr[max_n][m];
int ql,qr,ans;
for(int i=1;i<=n;i++)cin>>arr[i][0];
for(int i=1;i<=m;i++)
for(int j=1;j+(1<<i)-1<=n;j++)
arr[i][j]=max(arr[j][i-1],arr[j+(1<<(i-1))][j-1];
int k=log2(qr-ql+1);
ans=max/min(arr[l][k],arr[r-(1<<k)+1][k]);
```
3.并查集
```cpp
int fins(int u)
{
if(f[u]==u)return u;
return f[u]=fins(f[u]);
}
void merg(int x,int y)
{
x=fins(x);y=fins(y);
if(x!=y)f[x]=y;
}
```
***C.算法***
1.二分
//可取r时
```cpp
while(l<=r)
mid=l+(r-l)/2; //防爆
if(必要なら)l=mid+1;
else r=mid-1;
```
不可取r时
```cpp
while(l<r)
mid=l+(r-l)/2;
if(必要なら)l=mid+1;
else r=mid;
```
2.用于有序数组,数组的标号按升序/降序排列
~~只能用于有序,似乎没啥用~~
```cpp
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int> a(n);
vector<int> b(n);
for(int i=0;i<n;i++)b[i]=i;
for(int i=0;i<n;i++)cin>>a[i];
sort(b.begin(),b.end(),[&](int i,int j){
return a[i]>a[j];
});
for(auto &it:b)cout<<it<<" ";
cout<<endl;
}
```
·····使用场景Codeforces 1443C
[传送门](http://codeforces.com/contest/1443/problem/C)
大意:有a,b两个数组,两个数组元素数目相同。对于a数组每次可以选择小于某数的所有值,对于b数组只能单独选取某值,需要选择全部的1-n(a或b数组)
```cpp
int main(){
#ifdef memset0
freopen("1.in","r",stdin);
#endif
read(T);
while(T--){
read(n);
for(int i=1;i<=n;i++)read(a[i]);
for(int i=1;i<=n;i++)read(b[i]);
for(int i=1;i<=n;i++)id[i]=i;
sort(id+1,id+n+1,[&](int x,int y){
return a[x]<a[y];
});
sum[n+1]=0;
for(int i=n;i>=1;i--)sum[i]=sum[i+1]+b[id[i]];
long long ans=LLONG_MAX;
for(int i=0;i<=n;i++){
ans=min(ans,max<long long>(sum[i+1],a[id[i]]));
}
print(ans,'\n');
}
}
```
浙公网安备 33010602011771号