此文章将会持续更新,内容同步作者所学到的
代码模板
#include<bits/stdc++.h>
#define arrout(a,n) rep(i,1,n)std::cout<<a[i]<<" "
#define arrin(a,n) rep(i,1,n)std::cin>>a[i]
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define dep(i,x,n) for(int i=x;i>=n;i--)
#define erg(i,x) for(int i=head[x];i;i=e[i].nex)
#define dbg(x) std::cout<<#x<<":"<<x<<" "
#define mem(a,x) memset(a,x,sizeof a)
#define all(x) x.begin(),x.end()
#define arrall(a,n) a+1,a+1+n
#define PII std::pair<int,int>
#define m_p std::make_pair
#define u_b upper_bound
#define l_b lower_bound
#define p_b push_back
#define CD const double
#define CI const int
#define int long long
#define il inline
#define ss second
#define ff first
#define itn int
CI N=1e5+5;
signed main() {
return 0;
}
前缀和
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,a[N],b[N];
int main() {
ios::sync_with_stdio(false);
cin>>n>>m;
for (int i=1; i<=n; i++) {
cin>>a[i];
b[i]=a[i]+b[i-1];
}
for (int i=1; i<=m; i++) {
int x,y;
cin>>x>>y;
cout<<b[y]-b[x-1]<<endl;
}
return 0;
}
差分
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N],b[N];
int n,m,l,r,c,x;
int main() {
cin>>n>>m;
for (int i=1; i<=n; i++) {
cin>>a[i];
b[i]=a[i]-a[i-1];
}
while (m--) {
cin>>l>>r>>c;
b[l]+=c;
b[r+1]-=c;
}
for (int i=1; i<=n; i++) {
x+=b[i];
cout<<x<<" ";
}
return 0;
}
二分查找
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,a[N],x,ans;
int main() {
ios::sync_with_stdio(0);
cin>>n;
for (int i=1; i<=n; i++) {
cin>>a[i];
}
cin>>x;
int l=1,r=n;
while (l<=r) {
int mid=(l+r)>>1;
if (a[mid]==x) {
ans=mid,r=mid-1;
} else if (a[mid]<x) {
l=mid+1;
} else {
r=mid-1;
}
}
if (!ans) {
cout<<-1;
} else {
cout<<ans;
}
return 0;
}
逆序对
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N],r[N];
int sum,n;
void Msort(int left,int right) {
int mid=(right+left)/2;
if (left==right) {
return;
}
Msort(left,mid);
Msort(mid+1,right);
int i=left,j=mid+1,k=left;
while (i<=mid&&j<=right) {
if (a[i]<=a[j]) {
r[k]=a[i];
k++,i++;
} else {
r[k]=a[j];
k++,j++;
sum+=mid-i+1;
}
}
while (i<=mid) {
r[k]=a[i];
k++;
i++;
}
while (j<=right) {
r[k]=a[j];
j++;
k++;
}
for (int i=left; i<=right; i++) {
a[i]=r[i];
}
}
int main() {
cin>>n;
for (int i=1; i<=n; i++) {
cin>>a[i];
}
Msort(1,n);
cout<<sum;
}
计数排序(桶排)
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,x,a[N];
int main() {
cin>>n;
for (int i=1; i<=n; i++) {
cin>>x;
a[x]=x;
}
for (int i=0; i<=x; i++) {
if (a[i]) {
cout<<i<<' ';
a[i]=0;
}
}
}
快速排序
int n,a[100005],r[100005];
void Msort(int left,int right) {
int mid=(left+right)>>1;
if (left==right) {
return;
}
Msort(left,mid);
Msort(mid+1,right);
int i=left,j=mid+1,k=left;
while (i<=mid&&j<=right) {
if (a[i]<=a[j]) {
r[k]=a[i];
k++,i++;
} else {
r[k]=a[j];
k++,j++;
}
}
while (i<=mid) {
r[k]=a[i];
k++,i++;
}
while (j<=right) {
r[k]=a[j];
k++,j++;
}
for (int i=left; i<=right; i++) {
a[i]=r[i];
}
}
快速幂
int qpow(int a,int b,int q) {
if (b==0)
return 1%q;
else if (b%2==1)
return qpow(a,b-1,q)*a%q;
else {
int t=qpow(a,b/2,q);
return t*t%q;
}
}
快速幂(位运算)
int qpow(int a,int b,int q) {
if (b==0) {
return 1%q;
}
long long ans=1;
while (b) {
if (b&1) {
ans=ans*a%q;
}
a=a*a%q;
b>>=1;
}
return ans;
}
最长不下降子序列 LIS
#include <bits/stdc++.h>
using namespace std;
const int N=1e4+5;
int ans=INT_MIN,a[N],dp[N],n;
int main() {
cin>>n;
for (int i=1; i<=n; i++) {
dp[i]=1;
cin>>a[i];
}
for (int i=1; i<=n; i++) {
for (int j=1; j<=i; j++) {
if (a[i]>a[j]) {
dp[i]=max(dp[i],dp[j]+1);
}
}
}
for (int i=1; i<=n; i++) {
ans=max(ans,dp[i]);
}
cout<<ans;
return 0;
}
最长公共子序列 LCS
#include <bits/stdc++.h>
using namespace std;
const int N=2e3+5;
string a,b;
int len1,len2,dp[N][N];
int main() {
cin>>a>>b;
len1=a.size();
len2=b.size();
for (int i=1; i<=len1; i++) {
for (int j=1; j<=len2; j++) {
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
if (a[i-1]==b[j-1]) {
dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
}
}
}
cout<<dp[len1][len2];
return 0;
}
对拍
#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
int main() {
int ok=0;
int n;
printf("请输入你希望对拍的次数: ");
scanf("%d",&n);
for (int i=1; i<=n; ++i) {
system("make.exe > make.txt");
system("std.exe < make.txt > std.txt");
double begin=clock();
system("baoli.exe < make.txt > baoli.txt");
double end=clock();
double t=(end-begin);
if (system("fc std.txt baoli.txt")) {
printf("测试点#%d Wrong Answer\n",i);
} else if (t>1000) {
printf("测试点#%d Time Limited Exceeded 用时 %.0lfms\n",i,t);
} else {
printf("测试点#%d Accepted 用时%.0lfms\n",i,t);
ok++;
}
}
printf("\n");
double res=100.0*ok/n;
printf("共 %d 组测试数据,AC数据 %d 组。 得分%.1lf。",n,ok,res);
Sleep(1000);
}
生成区间序列
#include <bits/stdc++.h>
using namespace std;
int random(int mod) {
int n1,n2,n3,n4,ans;
n1=rand();
n2=rand();
n3=rand();
n4=rand();
ans=n1*n2%mod;
ans=ans*n3%mod;
ans=ans*n4%mod;
return ans;
}
int main() {
srand((unsigned)time(0));
int n,m;
for (int i=1; i<=m; i++) {
int l=random(n)+1;
int r=random(n)+1;
if (l>r)
swap(l,r);
printf("%d %d\n",l,r);
}
return 0;
}
生成树
#include <bits/stdc++.h>
using namespace std;
int random(int mod) {
int n1,n2,n3,n4,ans;
n1=rand();
n2=rand();
n3=rand();
n4=rand();
ans=n1*n2%mod;
ans=ans*n3%mod;
ans=ans*n4%mod;
return ans;
}
int main() {
srand((unsigned)time(0));
int n,size;
for (int i=2; i<=n; i++) {
int fa=random(i-1)+1;
int val=random(size)+1;
printf("%d %d %d\n",fa,i,val);
}
return 0;
}
生成整数序列
#include <bits/stdc++.h>
using namespace std;
int random(int mod) {
int n1,n2,n3,n4,ans;
n1=rand();
n2=rand();
n3=rand();
n4=rand();
ans=n1*n2%mod;
ans=ans*n3%mod;
ans=ans*n4%mod;
return ans;
}
int main() {
srand((unsigned)time(0));
int n_size,size,a[100005];
int n=random(n_size)+1;
for (int i=1; i<=n; i++) {
a[i]=random(2*size+1)-size;
}
return 0;
}
随机生成图
#include <bits/stdc++.h>
using namespace std;
int n,m;
int random(int mod) {
int n1,n2,n3,n4,ans;
n1=rand();
n2=rand();
n3=rand();
n4=rand();
ans=n1*n2%mod;
ans=ans*n3%mod;
ans=ans*n4%mod;
return ans;
}
int main() {
srand((unsigned)time(0));
pair<int,int> e[1000005];
map<pair<int,int>,bool> h;
cin>>n>>m;
for (int i=1; i<=n; i++) {
int fa=random(i)+1;
e[i]=make_pair(fa,i+1);
h[e[i]]=h[make_pair(i+1,fa)]=1;
}
for (int i=n; i<=m; i++) {
int x,y,l;
do {
x=random(n)+1;
y=random(n)+1;
} while (x==y||h[make_pair(x,y)]);
e[i]=make_pair(x,y);
h[e[i]]=h[make_pair(y,x)]=1;
}
random_shuffle(e+1,e+m+1);
for (int i=1; i<=m; i++) {
cout<<e[i].first<<' '<<e[i].second;
}
return 0;
}
树状数组
单点修改,区间查询
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int a[N],c[N],n,m,x;
int lowbit(int x) {
return x&(-x);
}
void update(int x,int v) {
for (int i=x; i<=n; i+=lowbit(i)) {
c[i]+=v;
}
}
int get(int l,int r) {
int ans=0;
for (int i=l-1; i; i-=lowbit(i)) {
ans-=c[i];
}
for (int i=r; i; i-=lowbit(i)) {
ans+=c[i];
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for (int i=1; i<=n; i++) {
cin>>a[i];
add(i,a[i]);
}
while (m--) {
int k,v;
cin>>x>>k>>v;
if (x) {
update(k,v);
} else {
cout<<get(k,v)<<"\n";
}
}
return 0;
}
区间修改,单点查询
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,a[N],c[N],b[N];
int lowbit(int x) {
return x&(-x);
}
void update(int k,int v) {
for (int i=k; i<=n; i+=lowbit(i)) {
c[i]+=v;
}
}
int get(int x) {
int ans=0;
for (int i=x; i; i-=lowbit(i)) {
ans+=c[i];
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for (int i=1; i<=n; i++) {
cin>>a[i];
b[i]=a[i]-a[i-1];
update(i,b[i]);
}
while (m--) {
int q,x,y,k;
cin>>q;
if (q==1) {
cin>>x>>y>>k;
update(x,k);
update(y+1,-k);
} else {
cin>>x;
cout<<get(x)<<"\n";
}
}
return 0;
}
区间修改,区间查询
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,a[N],b[N],c[N],maxn;
int lowbit(int a) {
return a&(-a);
}
void update(int x,int y) {
for (int i=x; i<=n; i+=lowbit(i)) {
b[i]+=y;
c[i]+=x*y;
}
}
void range_update(int l,int r,int x) {
update(l,x);
update(r+1,-x);
}
int query(int x) {
int ans=0;
for (int i=x; i; i-=lowbit(i)) {
ans+=(x+1)*b[i]-c[i];
}
return ans;
}
int range_query(int l,int r) {
return query(r)-query(l-1);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for (int i=1; i<=n; i++) {
cin>>a[i];
update(i,a[i]-a[i-1]);
}
for (int i=1; i<=m; i++) {
int q,x,y,k;
cin>>q;
if (q==1) {
cin>>x>>y>>k;
range_update(x,y,k);
} else {
cin>>x>>y;
cout<<range_query(x,y)<<endl;
}
}
return 0;
}
线段树
单点修改,区间查询
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int T,n,a[N<<2],s[N<<2];
void build(int k,int l,int r) {
if (l==r) {
s[k]=a[l];
return;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
s[k]=s[k<<1]+s[k<<1|1];
}
void update(int k,int l,int r,int x,int v) {
if (x<l||r<x) {
return;
}
if (l==r&&l==x) {
s[k]+=v;
return;
}
int mid=l+r>>1;
update(k<<1,l,mid,x,v);
update(k<<1|1,mid+1,r,x,v);
s[k]=s[k<<1]+s[k<<1|1];
}
int query(int k,int l,int r,int x,int y) {
if (y<l||r<x) {
return 0;
}
if (x<=l&&r<=y) {
return s[k];
}
int mid=l+r>>1,ans=0;
ans=query(k<<1,l,mid,x,y);
ans+=query(k<<1|1,mid+1,r,x,y);
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
int x,y;
for (int i=1; i<=n; i++) {
cin>>a[i];
}
build(1,1,n);
string q;
while (cin>>q) {
cin>>x>>y;
if (q=="Add") {
update(1,1,n,x,y);
} else if (q=="Query") {
cout<<query(1,1,n,x,y)<<"\n";
}
}
return 0;
}
区间修改,区间查询
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,s[N],lazy[N];
char op;
void build(int k,int l,int r) {
if (l==r) {
s[k]=a[l];
return;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
s[k]=s[k<<1]+s[k<<1|1];
}
void pushdown(int k,int l,int r) {
if (lazy[k]!=0) {
int mid=l+r>>1;
s[k<<1]+=(mid-l+1)*lazy[k];
lazy[k<<1]+=lazy[k];
s[k<<1|1]+=(r-mid)*lazy[k];
lazy[k<<1|1]+=lazy[k];
lazy[k]=0;
}
}
void update(int k,int l,int r,int x,int y,int v) {
if (y<l||r<x) {
return;
}
if (x<=l&&r<=y) {
s[k]+=(r-l+1)*v;
lazy[k]+=v;
return;
}
pushdown(k,l,r);
int mid=l+r>>1;
update(k<<1,l,mid,x,y,v);
update(k<<1|1,mid+1,r,x,y,v);
s[k]=s[k<<1]+s[k<<1|1];
}
int query(int k,int l,int r,int x,int y) {
if (y<l||r<x) {
return 0;
}
if (x<=l&&r<=y) {
return s[k];
}
pushdown(k,l,r);
int ans=0,mid=l+r>>1;
ans+=query(k<<1,l,mid,x,y);
ans+=query(k<<1|1,mid+1,r,x,y);
return ans;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for (int i=1; i<=n; i++) {
cin>>a[i];
}
build(1,1,n);
while (m--) {
int x,y,z;
cin>>op;
if (op=='Q') {
cin>>x>>y;
cout<<query(1,1,n,x,y)<<"\n";
} else {
cin>>x>>y>>z;
update(1,1,n,x,y,z);
}
}
return 0;
}
图的存储
const int N=1e5+5;
struct edge {
int to,nex;
}e[N];
int head[N],tot;
void add(int x,int y) {
e[++tot].to=y;
e[tot].nex=head[x];
head[x]=tot;
}
最短路
BFS最短路
#include <bits/stdc++.h>
using namespace std;
const int N=40;
int st,ed,n,vis[N],dis[N],e[N][N];
void BFS(int st,int ed) {
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(st);
vis[st]=1;
dis[st]=0;
while (!q.empty()) {
int x=q.front();
q.pop();
vis[x]=0;
for (int i=1; i<=ed; i++) {
if (e[x][i]==1&&vis[i]!=1) {
q.push(i);
vis[i]=1;
dis[i]=dis[x]+1;
if (i==ed) {
cout<<dis[i];
exit(0);
}
}
}
}
}
int main() {
cin>>st>>ed>>n;
for (int i=1; i<=n; i++) {
int x,y;
cin>>x>>y;
e[x][y]=1;
e[y][x]=1;
}
BFS(st,ed);
return 0;
}
Floyd
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
int n,m,st,ed,dp[N][N];
void Floyd() {
for (int k=1; k<=n; k++) {
for (int i=1; i<=n; i++) {
for (int j=1; j<=n; j++) {
if (dp[i][k]+dp[k][j]<dp[i][j]) {
dp[i][j]=dp[i][k]+dp[k][j];
}
}
}
}
}
int main() {
cin>>n>>m;
memset(dp,0x7f,sizeof(dp));
for (int i=1,x,y; i<=m; i++) {
cin>>x>>y;
dp[y][x]=dp[x][y]=1;
}
cin>>st>>ed;
Floyd();
cout<<dp[st][ed];
return 0;
}
Dijkstra
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,st,ed,head[N],dis[N],tot;
struct node {
int nex,to,data;
} a[N];
void add(int x,int y,int z) {
a[++tot].data=z;
a[tot].to=y;
a[tot].nex=head[x];
head[x]=tot;
}
struct edge {
int to,data;
bool operator<(const edge& b)const {
return data>b.data;
}
};
void Dijkstra(int st) {
memset(dis,0x3f,sizeof(dis));
dis[st]=0;
priority_queue<edge>q;
q.push(edge({ st,0 }));
while (!q.empty()) {
edge x=q.top();
q.pop();
int to=x.to;
int data=x.data;
if (data!=dis[to]) {
continue;
}
for (int i=head[to]; i; i=a[i].nex) {
int v=a[i].to;
int w=a[i].data;
if (dis[to]+w<dis[v]) {
dis[v]=dis[to]+w;
q.push(edge({ v,dis[v] }));
}
}
}
}
int main() {
cin>>n>>m>>st>>ed;
for (int i=1,x,y,z; i<=m; i++) {
cin>>x>>y>>z;
add(x,y,z);
add(y,x,z);
}
Dijkstra(st);
if (dis[ed]!=0x3f3f3f3f) {
cout<<dis[ed];
} else {
cout<<-1;
}
return 0;
}
/*
5 8 1 2
0 2 5
0 4 6
0 5 4
1 4 1
1 5 3
2 3 2
2 4 9
4 5 7
*/
SPFA
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,st,ed,tot;
int head[N],dis[N],cnt[N],vis[N];
struct node {
int to,data,nex;
} e[N];
void add(int x,int y,int z) {
e[++tot].to=y;
e[tot].data=z;
e[tot].nex=head[x];
head[x]=tot;
}
void SPFA(int st) {
queue<int>q;
dis[st]=0;
q.push(st);
while (!q.empty()) {
int x=q.front();
q.pop();
vis[x]=0;
for (int i=head[x]; i; i=e[i].nex) {
int y=e[i].to;
int z=e[i].data;
if (dis[y]>dis[x]+z) {
dis[y]=dis[x]+z;
cnt[y]=cnt[x]+1;
if (cnt[y]>n) {
cout<<"有负环"<<endl;
return;
}
if (!vis[y]) {
vis[y]=1;
q.push(y);
}
}
}
}
}
int main() {
cin>>n>>m>>st>>ed;
memset(dis,0x3f,sizeof(dis));
for (int i=1,x,y,z; i<=m; i++) {
cin>>x>>y>>z;
add(x,y,z);
}
SPFA(st);
if (dis[ed]!=0x3f3f3f3f) {
cout<<dis[ed];
} else {
cout<<-1;
}
return 0;
}
/*
5 8 1 2
0 2 5
0 4 6
0 5 4
1 4 1
1 5 3
2 3 2
2 4 9
4 5 7
*/
最小生成树
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
struct edge {
int from,to,data;
bool operator<(const edge b) const {
return data<b.data;
}
} e[N];
int n,f[N],ans;
int find(int x) {
return x==f[x]?x:f[x]=find(f[x]);
}
void add(int x,int y) {
if (find(x)!=find(y)) {
f[find(x)]=find(y);
}
}
int main() {
cin>>n;
for (int i=1; i<=n; i++) {
f[i]=i;
for (int j=1; j<=n; j++) {
int x;
cin>>x;
e[++f[0]]=(edge){i,j,x};
}
}
sort(e+1,e+1+f[0]);
int cnt=0;
for (int i=1; i<=f[0]; i++) {
if (find(e[i].from)!=find(e[i].to)) {
add(e[i].from,e[i].to);
ans+=e[i].data;
if (++cnt==n-1) {
break;
}
}
}
cout<<ans;
return 0;
}
数论
线性筛
int p[N],vis[N];
void prime() {
for (int i=2; i<=n; i++) {
if (!vis[i]) {
p[++p[0]]=i;
}
for (int j=1; j<=p[0]&&p[j]*i<=n; j++) {
vis[p[j]*i]=1;
if (i%p[j]==0) {
break;
}
}
}
}
唯一分解定理(质因数分解)
int p[N],vis[N];
void prime(int n) {
for (int i=2; i*i<=n; i++) {
if (c%i==0) {
p[++p[0]]=i,vis[p[0]]=0;
while (c%i==0) {
c/=i,vis[p[0]]++;
}
}
}
if (c>1) {
p[++p[0]]=c,a[p[0]]=1;
}
}
CRT
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,x,y,ans;
int a[24],m[24];
int exgcd(int a,int b,int& x,int& y) {
if (b==0) {
x=1,y=0;
return a;
}
int ret=exgcd(b,a%b,x,y);
int t=x;
x=y,y=t-(a/b)*y;
return ret;
}
int CRT(int a[],int m[],int n) {
int ans=0,M=1;
for (int i=1; i<=n; i++)
M*=m[i];
for (int i=1; i<=n; i++) {
int Mi=M/m[i];
exgcd(Mi,m[i],x,y);
ans=(ans+x*a[i]*Mi)%M;
}
if (ans<0) {
ans+=M;
}
return ans;
}
int main() {
ios::sync_with_stdio(0);
cin>>n;
for (int i=1; i<=n; i++) {
cin>>m[i]>>a[i];
}
ans=CRT(a,m,n);
cout<<ans;
return 0;
}
GCD
int gcd(int a,int b) {
if (!b) {
return a;
}
return gcd(b,a%b);
}
欧拉函数序列
int phi[1000005];
void euler(int n) {
for (int i=1; i<=n; i++) {
phi[i]=i;
}
phi[1]=1;
for (int i=2; i<n; i++) {
if (phi[i]==i) {
for (int j=i; j<n; j+=i) {
phi[j]=phi[j]/i*(i-1);
}
}
}
}
欧拉函数值
int euler(int n) {
int ans=n;
for (int i=1; i*i<=n; i++) {
if (n%i==0) {
ans=ans/i*(i-1);
while (n%i==0) {
n/=i;
}
}
}
if (n>1) {
ans-=ans/n;
}
return ans;
}
矩阵乘法
struct matrix {
int mat[N][N];
matrix() {
memset(mat,0,sizeof mat);
}
matrix operator*(const matrix& b)const {
matrix ans;
for (int i=1; i<=N; i++) {
for (int j=1; j<=N; j++) {
for (int k=1; k<=N; k++) {
ans.mat[i][j]=(ans.mat[i][j]+mat[i][k]*b.mat[k][j]%MOD)%MOD;
}
}
}
return ans;
}
};
矩阵快速幂
struct matrix {
int mat[N][N];
matrix() {
memset(mat,0,sizeof mat);
}
matrix operator*(const matrix& b)const {
matrix ans;
for (int i=1; i<=N; i++) {
for (int j=1; j<=N; j++) {
for (int k=1; k<=N; k++) {
ans.mat[i][j]=(ans.mat[i][j]+mat[i][k]*b.mat[k][j]%MOD)%MOD;
}
}
}
return ans;
}
};
matrix qpow(matrix a,int b){
matrix ans;
for(int i=1;i<=N;i++){
ans.mat[i][i]=1;
}
while(b){
if(b&1){
ans=ans*a;
}
a=a*a;
b>>=1;
}
}
组合数(Lucas定理)
int qpow(int a,int b) {
int ans=1;
while (b) {
if (b&1) {
ans=ans*a%MOD;
}
a=a*a%MOD;
b>>=1;
}
return ans;
}
int C(int n,int m) {
if (m<0) {
return 0;
}
if (n<m) {
return 0;
}
if (m>n-m) {
m=n-m;
}
int up=1,down=1;
for (int i=0; i<m; i++) {
up=up*(n-i)%MOD;
down=down*(i+1)%MOD;
}
return qpow(down,MOD-2)*up;
}
int Lucas(int n,int m) {
if (m==0) {
return 1;
} else {
return Lucas(n/MOD,m/MOD)%MOD*C(n%MOD,m%MOD)%MOD;
}
}
组合数(预处理阶乘+逆元)
int fac[N],inv[N];
int qpow(int a,int b) {
int ans=1;
while (b) {
if (b&1) {
ans=ans*ans%MOD;
}
a=a*a%MOD;
b>>=1;
}
return ans;
}
void pre() {
fac[0]=inv[0]=1;
for (int i=1; i<=N; i++) {
fac[i]=fac[i-1]*i%MOD;
}
inv[N]=qpow(fac[N],MOD-2);
for (int i=N-1; i>=0; i--) {
inv[i]=inv[i+1]*(i+1)%MOD;
}
}
int C(int n,int m) {
return fac[n]*inv[m]%MOD*inv[n-m]%MOD;
}