0.目录
重新开一个模板总结。
1.图论
并查集(from LeetCode)
class UnionFind {
public:
vector<int> parent;
vector<int> size;
int n;
int setCount;
public:
UnionFind(int _n): n(_n), setCount(_n), parent(_n), size(_n,1) {
iota(parent.begin(),parent.end(),0); //区间赋值
}
int findset(int x) {
return parent[x]==x ? x : parent[x]=findset(parent[x]);
}
bool unite(int x, int y) {
x=findset(x);
y=findset(y);
if (x==y) {
return false;
}
if (size[x]<size[y]) {
swap(x,y);
}
parent[y]=x;
size[x]+=size[y];
--setCount;
return true;
}
bool connected(int x,int y) {
x=findset(x);
y=findset(y);
return x==y;
}
};
Tarjan 求桥边(vector邻接表存图) (from LeetCode)
class TarjanSCC {
private:
const vector<vector<int>> &edges;
const vector<vector<int>> &edgesId;
vector<int> low;
vector<int> dfn;
vector<int> ans;
int n;
int ts;
private:
void getCuttingEdge_(int u, int parentEdgeId) {
low[u]=dfn[u]=++ts;
for (int i=0; i<edges[u].size(); ++i) {
int v=edges[u][i];
int id=edgesId[u][i];
if (dfn[v]==-1) {
getCuttingEdge_(v,id);
low[u]=min(low[u],low[v]);
if (low[v]>dfn[u]) {
ans.push_back(id);
}
}
else if (id!=parentEdgeId) {
low[u]=min(low[u],dfn[v]);
}
}
}
public:
TarjanSCC(int n_, const vector<vector<int>> &edges_, const vector<vector<int>> &edgesId_):\
edges(edges_), edgesId(edgesId_), low(n_,-1), dfn(n_,-1), n(n_), ts(-1){}
vector<int> getCuttingEdge() {
for (int i=0; i<n; ++i) {
if (dfn[i]==-1) {
getCuttingEdge_(i,-1);
}
}
return ans;
}
};
网络流
template <typename Cap = int64_t>
class Dinic{
private:
struct E{
int to, rev;
Cap cap;
};
int n, st, ed;
vector<vector<E>> G;
vector<int> lv, idx;
vector<pair<int, int>> egs;
bool BFS(){
lv.assign(n, -1);
queue<int> bfs;
bfs.push(st); lv[st] = 0;
while (not bfs.empty()){
int u = bfs.front(); bfs.pop();
for (auto e: G[u]) {
if (e.cap <= 0 or lv[e.to]!=-1) continue;
bfs.push(e.to); lv[e.to] = lv[u] + 1;
}
}
return lv[ed] != -1;
}
Cap DFS(int u, Cap f){
if (u == ed) return f;
Cap ret = 0;
for(int &i = idx[u]; i < int(G[u].size()); ++i) {
auto &e = G[u][i];
if (e.cap <= 0 or lv[e.to]!=lv[u]+1) continue;
Cap nf = DFS(e.to, min(f, e.cap));
ret += nf; e.cap -= nf; f -= nf;
G[e.to][e.rev].cap += nf;
if (f == 0) return ret;
}
if (ret == 0) lv[u] = -1;
return ret;
}
public:
void init(int n_) { G.assign(n = n_, vector<E>()); egs.clear(); }
void add_edge(int u, int v, Cap c){
G[u].push_back({v, int(G[v].size()), c});
G[v].push_back({u, int(G[u].size())-1, 0});
egs.emplace_back(v, int(G[v].size()) - 1);
}
Cap max_flow(int st_, int ed_){
st = st_, ed = ed_; Cap ret = 0;
while (BFS()) {
idx.assign(n, 0);
Cap f = DFS(st, numeric_limits<Cap>::max());
ret += f;
if (f == 0) break;
}
return ret;
}
Cap flow_at(int eid) const {
return G[egs[eid].first][egs[eid].second].cap;
}
};
2.数学
质数线性筛
#define MaxN 2000005
long long mn[MaxN],P[MaxN];
void mk_tb(long long *p, long long n) //打质数表,存到 p 数组,p[0] 为筛出的质数个数
{
for (long long i=2; i<=n; ++i) {
if (!mn[i]) p[mn[i]=++*p]=i;
for (long long j=1; j<=mn[i] && i*p[j]<=n; ++j) mn[i*p[j]]=j;
}
}
/*
前两百质数表
{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211,
223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563,
569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643,
647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739,
743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021,
1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093,
1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181,
1187, 1193, 1201, 1213, 1217, 1223}
*/
n的阶乘中质数 p 的次数
// n! 中 p 的次数
long long get_cntP(long long n, long long p)
{
long long ret=0;
while (n>1)
ret+= n/=p;
return ret;
}
遍历约数
#include <cstdio>
void test()
{
int t,k=1,cnt=0;
scanf("%d",&t);
while (k<t) {
if (t%k==0) printf("[%3d] %d\n",++cnt,k);
k=t/(t/(k+1));
}
puts(".");
}
void solve(int n)
{
int L=1,R=n;
while (L<R) {
if (n%L==0) printf("%d\n",L);
if (n%R==0) printf("%d\n",R);
R=n/(L+1);
L=n/R;
}
if (L==R && n%L==0) printf("%d\n",L);
puts("*\n");
}
/*
一百万以内约数个数前十的
{{240, 720720}, {240, 942480}, {240, 831600}, {240, 997920}, {240,
982800}, {224, 786240}, {224, 665280}, {224, 960960}, {216,
776160}, {216, 887040}}
*/
FWT(2021牛客6 D 的某个队提交的)
#include <bits/stdc++.h>
#define fp(i,a,b) for(int i=(a),_##i=(b)+1;i<_##i;++i)
#define fd(i,a,b) for(int i=(a),_##i=(b)-1;i>_##i;--i)
#define file(s) freopen(s".in","r",stdin)//,freopen(s".out","w",stdout)
template<class T>void In(T&x){
char c;T y=1;
while(c=getchar(),!isdigit(c)&&c!=-1){if(c=='-')y=-1;}x=c-'0';
while(c=getchar(),isdigit(c)){x=10*x+c-'0';}x*=y;
}
template<class T,class ...T_>void In(T&x,T_&...y){In(x),In(y...);}
using namespace std;
constexpr int N = 2e5 + 5, P = 1e9 + 7;
using db = double;
using arr = int[N];
using ll = long long;
/*---------------------------------------------------------------------------*/
#define ADD(a, b) ((a) += (b), (a) >= P ? (a) -=P : 0) // (a += b) %= P
#define SUB(a, b) ((a) -= (b), (a) < 0 ? (a) += P: 0) // ((a -= b) += P) %= P
//#define ADDE(a, b, c) ((a) = (b), ADD(a, c)) // a = (b + c) % P
//#define SUBE(a, b, c) ((a) = (b), SUB(a, c)) // a = (b - c + P) % P
#define INV(a) (POW(a, P - 2))
int POW(ll a,int b){ll x=1;for(;b>=1;b>>=1,a=a*a%P)if(b&1)x=x*a%P;return x;}
namespace FWT{
const ll I2 = (P + 1) >> 1;
int L;
void calc1(int &x, int &y) { int z = y; y = x, ADD(x, z), SUB(y, z); }
void calc2(int &x, int &y) { int z = y * I2 %P; x = x * I2 % P, y = x, ADD(x, z), SUB(y, z); }
void Init(int n) { for (L = 1; L < n; L <<= 1); }
void XOR(vector<int> &a, const int x) {
a.resize(L);
for (int o = 2, k = 1; o <= L; k = o, o <<= 1)
for (int i = 0; i < L; i += o)
fp(j, i, i + k - 1) x ? calc1(a[j], a[j + k]) : calc2(a[j], a[j + k]);
}
}
class Poly{
vector<int> a;
static Poly workFWT(void(*op)(vector<int>&,int),Poly&A,Poly&B){
FWT::Init(max(A.deg(),B.deg()));
op(A.a,1),op(B.a,1);
fp(i,0,FWT::L-1)A[i]=(ll)A[i]*B[i]%P;
return op(A.a,0),A;
}
public:
Poly(const vector<int>&t){a=t;}
Poly(int n=0){a.assign(n+1,0);}
int deg(){return(int)a.size()-1;}
int&operator[](const int&x){return a[x];}
template<class T>void copy(T b,int L,int x){std::copy(b,b+L,a.begin()+x);}
void Print(){fp(i,0,deg())printf("%d%c",a[i]," \n"[i==deg()]);}
friend Poly operator^(Poly A,Poly B){return workFWT(FWT::XOR,A,B);}
};
int n;arr p,sp,f,g;
void cdq(int L,int R,int Len){
if(L==R)return L==n-1?0:(f[L]=(ll)(f[L]+1)*INV(g[L])%P),void();
int m=(L+R)>>1,hL=Len>>1;
Poly a(hL),b(hL);
cdq(m+1,R,hL);
b.copy(p+hL,hL,0),a.copy(f+L+hL,hL,0),a=a^b;
fp(i,0,hL-1)f[L+i]=(f[L+i]+a[i])%P;
cdq(L,m,hL);
}
void Solve(){
fp(i,0,n-1)In(p[i]),sp[i]=sp[i-1]+p[i],g[i]=f[i]=0;
int m=log2(n),isp=INV(sp[n-1]);
fp(i,0,n-1)p[i]=(ll)p[i]*isp%P,sp[i]=(ll)sp[i]*isp%P;
fp(i,0,n-1)fp(j,0,m-1)if(!(i>>j&1))
ADD(g[i],sp[(1<<(j+1))-1]),SUB(g[i],sp[(1<<j)-1]);
cdq(0,n-1,n);
printf("%d\n",f[0]);
}
int main(){
#ifdef LOCAL
file("s");
#endif
In(n);
while(In(n),n!=-49)
Solve();
return 0;
}
exgcd
long long exgcd(long long aa,long long bb,long long &x,long long &y)//扩展欧几里得算法
{
if(bb==0)
{
x=1;y=0;
return aa; //到达递归边界开始向上一层返回
}
long long r=exgcd(bb,aa%bb,x,y);
long long temp=y; //把x y变成上一层的
y=x-(aa/bb)*y;
x=temp;
return r; //得到a b的最大公因数
}
组合数(含阶乘)
#define Ha 998244353
typedef long long LL;
LL jc[100005];
LL ksm(LL x, LL t) //快速幂 x^t
{
LL ret=1;
for (; t; (t>>=1),(x=x*x%Ha)) if (t&1) ret=ret*x%Ha;
return ret;
}
LL C(LL x, LL y) //组合数 x 选 y
{
if (y>x || y<0) return 0;
LL ret=jc[x];
ret=ret*ksm(jc[y],Ha-2)%Ha;
ret=ret*ksm(jc[x-y],Ha-2)%Ha;
return ret;
}
int main() {
//预处理阶乘
jc[0]=jc[1]=1;
for (int i=2; i<=100000; i++) {
jc[i]=(jc[i-1]*i)%Ha;
}
return 0;
}
高精度模板(来自 https://www.luogu.com.cn/blog/xuanxue/solution-p1303)
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define LL long long
using namespace std;
int m;
const long long mod=40961,G=3,Ginv=(mod+1)/3;
int r[240100];
LL ksm(LL a,LL b,LL mod)
{
LL ans=1;
for(;b;b>>=1,a=a*a%mod)
if(b&1)ans=ans*a%mod;
return ans;
}
void NTT(int limit,LL *l,int opt)
{
for(int i=0;i<limit;++i)
if(i<r[i])swap(l[i],l[r[i]]);
for(int mid=1;mid<limit;mid<<=1)
{
LL wn,len=mid<<1;;
if(opt==1)wn=ksm(G,(mod-1)/len,mod);
else wn=ksm(Ginv,(mod-1)/len,mod);
for(int j=0;j<limit;j+=len)
{
LL w=1;
for(int k=j;k<mid+j;++k,(w*=wn)%=mod)
{
int x=l[k],y=w*l[k+mid]%mod;
l[k]=(x+y)%mod;
l[k+mid]=(x-y+mod)%mod;
}
}
}
if(opt==-1)
{
LL inv=ksm(limit,mod-2,mod);
for(int i=0;i<=limit;i++) l[i]=l[i]*inv%mod;
}
}
/*------以下为重载部分------*/
struct gj
{
int len,zheng;//len:长度 zheng:正负标记0为负1为正
LL v[5000];
gj(){len=0;memset(v,0,sizeof(v));zheng=1;}
gj(int x)
{
if(x>=0)zheng=1;
else x=-x,zheng=0;
len=0;memset(v,0,sizeof(v));
while(x)
{
v[++len]=x%10;
x/=10;
}
}
friend bool operator <(const gj &a,const gj &b)
{
if(a.len<b.len)return 1;
if(a.len>b.len)return 0;
for(int i=a.len;i>=1;--i)
{
if(a.v[i]<b.v[i])return 1;
if(a.v[i]>b.v[i])return 0;
}
return 0;
}
}n,a,b;
ostream& operator << (ostream &out,const gj &a);
istream& operator >> (istream &in,gj &a);
gj operator -(gj a,gj b);
gj operator +(gj a,gj b);
gj operator *(gj a,gj b);
gj operator +(gj a,gj b)
{
if(!a.zheng&&!b.zheng)
{
a.zheng=b.zheng=1;
gj c=a+b;
c.zheng=0;
return c;
}
if(!a.zheng&&b.zheng)
{
a.zheng=b.zheng=1;
return b-a;
}
if(a.zheng&&!b.zheng)
{
a.zheng=b.zheng=1;
return a-b;
}
int len=a.len+b.len;
gj c;
c.len=len;
for(int i=1;i<=len;++i)c.v[i]=a.v[i]+b.v[i];
for(int i=1;i<=len;++i)
{
if(c.v[i]>=10)
{
++c.v[i+1];
c.v[i]-=10;
}
}
while(c.len&&!c.v[c.len])c.len--;
return c;
}
gj operator -(gj a,gj b)
{
if(!a.zheng&&!b.zheng)
{
a.zheng=b.zheng=1;
return b-a;
}
if(!a.zheng&&b.zheng)
{
a.zheng=1;
gj c=a+b;
c.zheng=0;
return c;
}
if(a.zheng&&!b.zheng)
{
b.zheng=1;
gj c=a+b;
return c;
}
if(a.zheng&&b.zheng&&a<b)
{
gj c=b-a;
c.zheng=0;
return c;
}
int len=max(a.len,b.len);
gj c;
for(int i=1;i<=len;++i)c.v[i]=a.v[i]-b.v[i];
c.len=len;
for(int i=1;i<=c.len;++i)
{
if(c.v[i]<0)
{
c.v[i+1]--;
c.v[i]+=10;
}
}
while(c.len&&!c.v[c.len])c.len--;
return c;
}
gj operator *(gj a,gj b)
{
int limit=1,tot,l=0;
gj c;
a.len--;b.len--;
for(int i=0;i<=a.len;++i)a.v[i]=a.v[i+1];a.v[a.len+1]=0;
for(int i=0;i<=b.len;++i)b.v[i]=b.v[i+1];b.v[b.len+1]=0;
while(limit<=a.len+b.len)limit<<=1,l++;
for(int i=0;i<=limit;i++) r[i]=(r[i>>1]>>1) | ((i&1)<<(l-1) );
NTT(limit,a.v,1);NTT(limit,b.v,1);
for(int i=0;i<=limit;i++) a.v[i]=a.v[i]*b.v[i]%mod;
NTT(limit,a.v,-1);
for(int i=0;i<=limit;i++) c.v[i]=a.v[i];
for(int i=0;i<=limit;i++)
{
if(c.v[i]>=10)
{
c.v[i+1]+=c.v[i]/10,c.v[i]%=10;
if(i+1>limit) limit++;
}
}
for(int i=limit;i>=0;i--)if(c.v[i]==0) limit--;else break;
c.len=limit+1;
for(int i=c.len;i>=1;--i)c.v[i]=c.v[i-1];c.v[0]=0;
for(int i=1;i<=c.len;++i)swap(c.v[i],c.v[c.len-i+1]);
if(a.zheng!=b.zheng)c.zheng=0;
else c.zheng=1;
return c;
}
gj operator /(gj a,long long b)
{
gj c;int d=0;
for(int i=a.len;i>=1;--i)
c.v[++c.len]=((d*10+a.v[i])/b),d=(d*10+a.v[i])%b;
for(int i=1;i<=c.len/2;++i)swap(c.v[i],c.v[c.len-i+1]);
if(!a.len||!b||(a.zheng&&b>0)||(!a.zheng&&b<0))c.zheng=1;
else c.zheng=0;
while(c.v[c.len]==0&&c.len>1)--c.len;
return c;
}
istream& operator >> (istream &in,gj &a)//方便使用cin
{
char lin[5010];int len;
scanf("%s",lin+1);
len=a.len=strlen(lin+1);
if(lin[1]=='-')a.zheng=0,a.len--;
else a.zheng=1;
for(int i=1;i<=a.len;++i)a.v[i]=lin[len-i+1]-'0';
return in;
}
ostream& operator << (ostream &out,const gj &a)//方便使用cout
{
if(!a.len)//一定要注意答案是0得情况
{
cout<<"0";
return out;
}
if(!a.zheng)cout<<"-";
for(int i=a.len;i>=1;i--)printf("%d",a.v[i]);
return out;
}
/*------以上为重载部分------*/
int main()
{
cin>>a>>b;
cout<<a*b;
return 0;
}
文件目录遍历
void testAllFiles(string path)
{
long hFile = 0; //文件信息
struct _finddata_t fileinfo; //存储文件信息的结构体
string p;
if ((hFile = _findfirst(p.assign(path).append("/*").c_str(), &fileinfo)) != -1) { //第一次查找
do {
if ((fileinfo.attrib & _A_SUBDIR)) { //若找到的是文件夹
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) {
testAllFiles(p.assign(path).append("/").append(fileinfo.name)); //递归进入文件夹
}
}
else { //若找到的不是文件夹
}
} while (_findnext(hFile, &fileinfo) == 0);
}
_findclose(hFile); //结束查找
}