模板大全
模板大全
写着写着放弃了(实则是退役了)
快读快写
inline int read() {
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
template<typename F>
inline void write(F x, char ed = '\n')
{
static short st[30];short tp=0;
if(x<0) putchar('-'),x=-x;
do st[++tp]=x%10,x/=10; while(x);
while(tp) putchar('0'|st[tp--]);
putchar(ed);
}
数学
看 :
算数基本定理
模运算(余数)
$amodP=a-\left\lfloor\dfrac{a}{P}\right\rfloor *P $$
扩展欧几里得
int x,y;
int exgcd(int a,int b) {
if(!b) {x=1,y=0;return a;}
int ans=exgcd(b,a%b),tmp=x;
x=y;y=tmp-a/b*y;
return ans;
}
void exgcd(ll a,ll b){
if(!b) {x=1,y=0;return;}
exgcd(b,a%b);
ll t=x;
x=y;
y=t-(a/b)*y;
}
最小整数解 $$ x=(x% b+b)%b $$
逆元
费马小定理
qpow(x,p-2);
线性递推
inv[1]=1;
for(int i=2;i<=n;i++)
inv[i]=(ll)p-(p/i)*inv[p%i]%p;
线性筛
for(int i=2;i<=n;i++){
if(!mindiv[i]) mindiv[i]=prime[++prime[0]]=i;
for(int j=1;j<=prime[0]&&i*prime[j]<=n&&prime[j]<=mindiv[i];j++)
mindiv[i*prime[j]]=prime[j];
}
筛phi
void PHI(int x){
phi[1]=1;
for(int i=2;i<=x;i++){
if(!mindiv[i]) mindiv[i]=p[++p[0]]=i,phi[i]=i-1;
for(int j=1;j<=p[0]&&i*p[j]<=x;j++){
mindiv[i*p[j]]=p[j];
if(i%p[j]==0){
phi[i*p[j]]=phi[i]*p[j];
break;
}else phi[i*p[j]]=phi[i]*phi[p[j]];
}
}
}
筛约数个数,约数和
https://blog.csdn.net/controlbear/article/details/77527115
#include<cstdio>
#include<algorithm>
typedef long long ll;
inline int gi(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=1000001;
int prime[N],d[N],f[N];
bool mindiv[N];
int main(){
int n=gi();
for(int i=1;i<=n;++i) d[i]=1;
for(int i=2;i<=n;++i){
if(!mindiv[i]) prime[++prime[0]]=i,d[i]=2,f[i]=1;
for(int j=1;i*prime[j]<=n&&j<=prime[0];++j){
mindiv[i*prime[j]]=1;
if(i%prime[j]==0){
f[i*prime[j]]=f[i]+1;
d[i*prime[j]]=d[i]/(f[i]+1)*(f[i*prime[j]]+1);
break;
}
f[i*prime[j]]=1;
d[i*prime[j]]=d[i]*d[prime[j]];
}
}
ll ans=0;
for(int i=1;i<=n;++i) ans+=d[i];
printf("%lld\n",ans);
return 0;
}
sd[1]=1;
for(int i=2;i<=n;++i){
if(!mindiv[i]) prime[++prime[0]]=i,sd[i]=sp[i]=i+1;
for(int j=1;i*prime[j]<=n&&j<=prime[0];++j){
mindiv[i*prime[j]]=1;
if(i%prime[j]==0){
sp[i*prime[j]]=sp[i]*prime[j]+1;
sd[i*prime[j]]=sd[i]/sp[i]*sp[i*prime[j]];
break;
}
sp[i*prime[j]]=1+prime[j];
sd[i*prime[j]]=sd[i]*sd[prime[j]];
}
}
生成质数的范围是[m,n] (1 <= m <= n <= 10^9, n-m<=1000000)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 10000003
using namespace std;
int pd[N],prime[N],T,l,r,vis[N];//prime[0]
void init(){
pd[1]=1;
for(int i=2;i<=100000;i++){
if(!pd[i])prime[++prime[0]]=i;
for(int j=1;j<=prime[0];j++){
if(i*prime[j]>100000)break;
pd[prime[j]*i]=1;
if(i%prime[j]==0)break;
}
}
}
int main(){
init();
scanf("%d",&T);
for(int i=1;i<=T;i++){
scanf("%d%d",&l,&r);
for(int j=1;j<=prime[0];j++){
int t=(l-1)/prime[j]+1;
if(t<=1)t=2;
for(int k=t*prime[j];k<=r;k+=prime[j])
vis[k-l+1]=i;
}
for(int j=1;j<=r-l+1;j++)
if(vis[j]!=i && j+l-1!=1)printf("%d\n",j+l-1);
puts("");
}
return 0;
}
矩阵快速幂
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
#define maxn 105
#define mod 1000000007
inline ll read(){
ll f=1,x=0; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=getchar();
return f*x;
}
ll k;
int n;
struct jz{
ll a[maxn][maxn]; //一定要用long long存矩阵,否则在过程中会爆掉
jz(){
memset(a,0,sizeof a);
}
inline void build(){ //建造单位矩阵
for(int i=1;i<=n;++i)a[i][i]=1;
}
}a,ans;
jz operator * (const jz &x,const jz &y){ //重载运算符
jz z;
for(int k=1;k<=n;++k)
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
z.a[i][j]=(z.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
return z;
}
int main(){
n=read();k=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
a.a[i][j]=read();
ans.build();
do{
if(k&1)ans=ans*a;
a=a*a;
k>>=1;
}while(k);
for(int i=1;i<=n;putchar('\n'),++i)
for(int j=1;j<=n;++j)
printf("%d ",ans.a[i][j]);
return 0;
}
图论
dp
区间dp
大概的板子——Q-key
一定要注意小的合并成大的中间需要的贡献
for(int len=1;len<=n;len++)
for(int l=1;l<=(n<<1)&&l+len<=(n<<1);l++) {
int r=l+len;
f[l][r]=0x3f3f3f3f;//Q
for(int k=l;k<r;k++) {
f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+sum[l][r]);
g[l][r]=max(g[l][r],g[l][k]+g[k+1][r]+sum[l][r]);
}
}