CSP前的板子们

Ryan_

2019-10-05 14:19:13

Personal

**矩阵乘法(矩阵快速幂)** ``` #include<cstdio> #include<cstring> using namespace std; long long n,a[3],mul[3][3],res[3][3],tmp[3][3],tp[3]; void mul_1() { memset(tmp,0,sizeof(tmp)); for(register int i=1;i<=2;i+=1) for(register int j=1;j<=2;j+=1) for(register int k=1;k<=2;k+=1) tmp[i][j]=(tmp[i][j]+res[i][k]*mul[k][j])%1000000007; for(register int i=1;i<=2;i+=1) for(register int j=1;j<=2;j+=1) res[i][j]=tmp[i][j]; } void mul_2() { memset(tmp,0,sizeof(tmp)); for(register int i=1;i<=2;i+=1) for(register int j=1;j<=2;j+=1) for(register int k=1;k<=2;k+=1) tmp[i][j]=(tmp[i][j]+mul[i][k]*mul[k][j])%1000000007; for(register int i=1;i<=2;i+=1) for(register int j=1;j<=2;j+=1) mul[i][j]=tmp[i][j]; } void solve() { for(register int i=1;i<=2;i+=1) for(register int j=1;j<=2;j+=1) tp[i]=(tp[i]+res[i][j]*a[j])%1000000007; printf("%lld\n",tp[1]); } int main() { scanf("%lld",&n); if(n<=2)printf("1\n"); else { a[1]=a[2]=1; for(register int i=1;i<=2;i+=1) res[i][i]=1; for(register int i=1;i<=2;i+=1) for(register int j=1;j<=2;j+=1) mul[i][j]=1; mul[2][2]=0; n-=2; while(n) { if(n&1)mul_1(); n>>=1; mul_2(); } solve(); } return 0; } ``` ``` #include<cstdio> #include<cstring> #define rei register int #define ll long long using namespace std; const int mod = 1000; ll n; struct Matrix { ll a[3][3]; } A, temp; Matrix M_mul(Matrix x, Matrix y) { memset(temp.a,0,sizeof(temp.a) ); for(int i=1; i<=2; ++i) for(int j=1; j<=2; ++j) for(int k=1; k<=2; ++k) temp.a[i][j] = ( temp.a[i][j]%mod + (x.a[i][k]%mod)*(y.a[k][j]%mod)%mod )%mod; return temp; } Matrix ksm(Matrix A, ll k) { Matrix ans; Matrix base = A; memset(ans.a,0,sizeof(ans.a) ); ans.a[1][1] = ans.a[2][2] = 1; while(k) { if(k&1) ans = M_mul(ans,base); base = M_mul(base,base); k>>=1; } return ans; } int main() { scanf("%lld",&n); if(n&1 || n==2) return printf("0"), 0; if(n==4) return printf("1"), 0; n>>=1; A.a[1][1] = 4, A.a[1][2] = -2, A.a[2][1] = 1; Matrix ans = ksm(A,n-2); printf("%lld",(2*ans.a[1][1]%mod +mod)%mod ); return 0; } ``` **广搜** ``` #include<cstdio> using namespace std; const int MAXM = 2*1e7 +5; const int W[5][2] = { {0,0}, {-2,1}, {-1,2}, {1,2}, {2,1} }; int n, m; int ans; struct node { int x, y; }q[MAXM]; int head = 1, tail = 0; void bfs() { while(head<=tail) { for(int i=1;i<=4;++i) { int xx = q[head].x + W[i][0], yy = q[head].y + W[i][1]; if(xx==n && yy==m) { ans++; continue; }//满足就统计 if(xx>=0 && yy<=m && xx<=n && yy>=0 ) q[++tail].x = xx, q[tail].y = yy; } head++; } return ; } int main() { scanf("%d%d",&n,&m); q[++tail].x = 0, q[tail].y = 0; bfs(); printf("%d",ans); return 0; } ``` **判断两序列的公共最长子序列** ``` #include<bits/stdc++.h> using namespace std; const int N=105; int f[N][N],a[N],b[N],n,m,cnt=0; int main(){ while(scanf("%d%d",&n,&m)!=EOF){ if(n==0&&m==0)break; for(int i=0;i<n;i++)scanf("%d",&a[i]); for(int i=0;i<m;i++)scanf("%d",&b[i]); memset(f,0,sizeof(f)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(a[i-1]==b[j-1])f[i][j]=f[i-1][j-1]+1; else f[i][j]=max(f[i-1][j],f[i][j-1]); } printf("Twin Towers #%d\nNumber of Tiles : %d\n", ++cnt, f[n][m]); puts(""); } return 0; } ``` **求与n互质的第k个正整数** ``` #include<bits/stdc++.h> using namespace std; const int N=1e6+5; int n,k; int a[N],cnt; int main(){ cin>>n>>k; for(int i=1;i<n;i++) if(__gcd(i,n)==1) a[++cnt]=i; printf("%d",(k-1)/cnt*n+a[(k-1)%cnt+1]); return 0; } ``` **最小生成树prim算法** ``` #include<iostream> #include<cstdio> #include<cstring> #define inf 2147483647 using namespace std; const int N=1000005; int nxt[N],go[N],first[N],tot,w[N],d[N],n,m,now=1,tot1,ans; bool v[N]; void add(int x,int y,int z) { nxt[++tot]=first[x]; first[x]=tot; go[tot]=y; w[tot]=z; } int prim() { for(int i=first[1]; i; i=nxt[i]) { d[go[i]]=min(d[go[i]],w[i]); } while(++tot1<n) { int minn=inf; v[now]=1; for(int i=1; i<=n; i++) { if(!v[i]&&minn>d[i]) { minn=d[i]; now=i; } } ans+=minn; for(int i=first[now]; i; i=nxt[i]) { int y=go[i]; if(d[y]>w[i]&&!v[y]) { d[y]=w[i]; } } } return ans; } int main() { cin>>n>>m; for(int i=1; i<=m; i++) { int a,b,c; cin>>a>>b>>c; add(a,b,c); add(b,a,c); } for(int i=1;i<=n;i++)d[i]=inf; //memset(v,0,sizeof(v)); d[1]=0; printf("%d",prim()); return 0; } ``` **对拍** ``` #include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; int main() { while(1) { system("rand.exe"); system("baoli.exe"); system("my.exe"); if(system("fc baoli.txt my.txt ")) while(1); } return 0; } --------------------------------------------------------------------------------------------------------------------------------------------- #include<iostream> #include<cstring> #include<ctime> #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; int main() { freopen("rand.txt","w",stdout); srand(time(0)); int n;n=rand()%5+1; cout<<n<<endl; for(int i=1;i<=n;i++) { int x;x=rand()%100+2; cout<<x<<" "; } return 0; } 生成的数据 ``` **求最大波形数据** ``` #include<bits/stdc++.h> using namespace std; int n,h[1000005],ans=1; bool con; int main() { cin>>n; for(int i=1; i<=n; i++) cin>>h[i]; if(h[2]>=h[1]) con=1; for(int i=1; i<=n; i++) { if(con==0&&i==n) { ans++; break; } if(con==1) if(h[i+1]<h[i]) { ans++; con=0; continue; } if(con==0) if(h[i+1]>h[i]) { ans++; con=1; continue; } } cout<<ans; } #include <stdio.h> int flag = 0, now, last, n, ans = 1; int main() { scanf("%d%d", &n, &now); while (--n) { last = now; scanf("%d", &now); if (now == last) continue; if (flag ^ (now < last)) ans++, flag = now < last; } printf("%d\n", ans); return 0; } ``` **最短路** dijkstra复杂度m*log(m)/n*n ``` void dijkstra(int x){ priority_queue<int,vector<int>,less<int> >q; memset(d,0x7f,sizeof(d)); memset(v,0,sizeof(v)); d[x]=0; q.push(make_mair(0,x)); while(q.size()){ int x=q.top().second;q.pop(); //if(v[x])continue; v[x]=1; for(int i=first[x];i;i=nxt[i]){ int y=go[i],z=w[i]; if(d[y]>d[x]+z){ d[y]=d[x]+z; if(!v[y])q.push(make_pair(-d[y],y)); } } } } ``` spfa复杂度km(k为较小的常数)/n*m(可用于求正负最短路,可判负环) ``` void spfa(int x) { queue<int> q; memset(hh,0,sizeof(hh));//判负环 memset(d,0x7f,sizeof(d)); memset(v,0,sizeof(v)); d[x]=0,v[x]=1;//入队 q.push(x); hh[x]++; while(q.size()) { int x=q.top(); pop(); v[x]=0; for(int i=first[x]; i; i=nxt[i]) { int y=go[i],z=w[i]; if(d[y]>d[x]+z) { d[y]=d[x]+z; if(!v[y])q.push(y),v[y]=1; hh[y]++; if(hh[y]>=n)cout<<"-1",exit(0);//出现负环 } } } } ``` **树的重心** ``` #include<cstdio> #include<iostream> #define inf 2147483647 using namespace std; const int N=100010; long long nxt[N<<1],go[N],tot,first[N],w[N],n,size[N],f[N]; long long min(long long a,long long b){ return a>b?b:a; } long long ans=inf; void add(int x,int y) { nxt[++tot]=first[x]; first[x]=tot; go[tot]=y; } void dfs(int u,int fa,int dep) { size[u]=w[u]; for(int i=first[u]; i; i=nxt[i]) { if(go[i]!=fa)dfs(go[i],u,dep+1),size[u]+=size[go[i]]; } f[1]+=w[u]*dep; } void dp(int u,int fa) { for(int i=first[u]; i; i=nxt[i]) if(go[i]!=fa) f[go[i]]=f[u]+size[1]-size[go[i]]*2,dp(go[i],u); ans=min(ans,f[u]); } int main() { //freopen("1.in","r",stdin); //freopen("1.out","w",stdout); cin>>n; ans*=ans; for(int i=1; i<=n; i++) { int a,b; cin>>w[i]; cin>>a>>b; if(a)add(i,a),add(a,i); if(b)add(i,b),add(b,i); } dfs(1,0,0); dp(1,0); printf("%lld",ans); return 0; } ------------------------------------------- #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,q; const int N=600001; int nxt[N],first[N],go[N],tot,size[N],f[N],ans[N],fa[N]; void add(int x,int y) { nxt[++tot]=first[x]; first[x]=tot; go[tot]=y; } void dfs(int x) { ans[x]=x; size[x]=1; int maxn=0,t=0; for(int i=first[x]; i; i=nxt[i]) { int v=go[i]; dfs(v); size[x]+=size[v]; if(size[v]>maxn) { maxn=size[v]; t=v; } } f[x]=maxn; if(f[x]*2<size[x])ans[x]=x; else { int now=ans[t]; while(fa[now]&&(f[now],size[x]-size[now])>max(f[fa[now]],size[x]-size[fa[now]]))now=fa[now]; ans[x]=now; } } int main() { cin>>n>>q; for(int i=2; i<=n; i++) { int k; cin>>k; fa[i]=k; add(k,i); } dfs(1); for(int i=1; i<=q; i++) { int k; cin>>k; cout<<ans[k]<<endl; } } ``` **网络流—EK算法** ``` #include<bits/stdc++.h> using namespace std; const int inf=1<<30; const int M=200005; int n,m,s,t; int nxt[M],first[M],go[M],tot=1,w[M]; inline int read(){ char c=getchar(); int x=0,f=1; while(!isdigit(c)){ if(c=='-')f=-1; c=getchar(); } while(isdigit(c)){ x=x*10+c-'0'; c=getchar(); } return x*f; } void add(int x,int y,int z){ nxt[++tot]=first[x];first[x]=tot;go[tot]=y;w[tot]=z; } bool inque[M]; struct node{ int v; int edge; }pre[M]; inline bool bfs(){ queue<int> q; memset(inque,0,sizeof inque); memset(pre,-1,sizeof pre); inque[s]=1; q.push(s); while(q.size()){ int u=q.front();q.pop(); for(int i=first[u];i;i=nxt[i]){ int d=go[i]; if(!inque[d]&&w[i]){ pre[d].v=u; pre[d].edge=i; if(d==t)return 1; inque[d]=1; q.push(d); } } } return 0; } int EK(){ int ans=0; while(bfs()){ int mi=inf; for(int i=t;i!=s;i=pre[i].v){ mi=min(mi,w[pre[i].edge]); } for(int i=t;i!=s;i=pre[i].v){ w[pre[i].edge]-=mi; w[pre[i].edge^1]+=mi; } ans+=mi; } return ans; } int main(){ register int i; n=read();m=read();s=read();t=read(); for(i=1;i<=m;i++){ int a,b,c; a=read();b=read();c=read(); add(a,b,c); add(b,a,0); } printf("%d",EK()); return 0; } ``` **LCIS问题** ``` #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int MAXN=5005; int N, M, A[MAXN], B[MAXN]; int f[MAXN][MAXN], ansj=0, lcis[MAXN][MAXN]; void LCIS(); void Input(); int main() { Input(); LCIS(); printf("%d\n",f[N][ansj]); for (int p=1; p<=f[N][ansj]; p++) printf("%d ",lcis[ansj][p]); puts(""); return 0; } void LCIS() { memset (f, 0, sizeof(f)); memset (lcis, 0, sizeof(lcis)); for (int i=1; i<=N; i++) { for (int j=1,k=0; j<=M; j++) { if (A[i] == B[j]) { f[i][j] = f[i-1][k]+1; for (int p=1; p<=f[i-1][k]; p++) lcis[j][p] = lcis[k][p]; lcis[j][f[i][j]] = A[i]; } else f[i][j] = f[i-1][j]; if (B[j]<A[i] && f[i][j]>f[i][k]) k = j; } } for (int i=1; i<=M; i++) if (f[N][i] > f[N][ansj]) ansj = i; return; } void Input() { scanf("%d",&N); for(int i=1; i<=N; i++) scanf("%d",&A[i]); scanf("%d",&M); for(int i=1; i<=M; i++) scanf("%d",&B[i]); return; } ``` **数学方法计算第一行中间列为1的幻方** ``` #include<cstdio> using namespace std; int n,a[40][40],x,y; int main(){ scanf("%d",&n); x=1,y=(n+1)/2; for(int i=1;i<=n*n;i++){ a[x][y]=i; if(!a[(x-2+n)%n+1][y%n+1]) x=(x-2+n)%n+1,y=y%n+1; else x=x%n+1;//数学运算 } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ printf("%d ",a[i][j]); } printf("\n"); } } ``` **求数的因子较为快速的一种方法** ``` #include<bits/stdc++.h> using namespace std; int main(){ long long n,ans=1; cin>>n; int k=sqrt(n); for(int i=2;i<=k;i++){ long long tot=1; while(n%i==0){ n/=i; tot++; } ans*=tot; } if(n>1)ans*=2; cout<<ans; return 0; } ``` **LCS** ``` #include<bits/stdc++.h> using namespace std; string a,b; int f[1001][1001]; int main() { cin>>a>>b; int len1=a.length(); int len2=b.length(); for(int i=1; i<=len1; i++) for(int j=1; j<=len2; j++) { f[i][j]=max(f[i-1][j],f[i][j-1]); if(a[i-1]==b[j-1])f[i][j]=max(f[i][j],f[i-1][j-1]+1); } cout<<f[len1][len2]; } ``` **Longest discontinuous ascending substring** 最长不连续上升子串 ``` #include<bits/stdc++.h> using namespace std; int n,m,k,f[1001][1001][11][2]; char s[1001],t[1001]; int main(){ int i,j,l; cin>>n>>m>>k; scanf("%s",s+1),scanf("%s",t+1); for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ if(s[i]==t[j]){ for(l=1;l<=k;l++){ f[i][j][l][0]=max(f[i-1][j-1][l][0],f[i-1][j-1][l-1][1])+1; } } for(l=1;l<=k;l++)f[i][j][l][1]=max(f[i-1][j][l][1],max(f[i][j-1][l][1],f[i][j][l][0])); } } cout<<f[n][m][k][1]<<endl; return 0; } ``` **求l至r的质数个数** ``` #include<bits/stdc++.h> #define int long long using namespace std; const int maxn = 1000000; int l , r; int prime[maxn] , cnt , tot; bool vis[maxn]; bool ans[maxn]; void getprime() { for(int i = 2 ; i <= 50000 ; ++ i) { if(!vis[i]) { prime[++cnt] = i; for(int j = i + i ; j <= 50000 ; j += i) { vis[j] = 1; } } } } long long maxnn(int a,int b) { return a>b?a:b; } signed main () { getprime(); scanf("%d%d" , & l ,& r); for(int i = 1 ; i <= cnt ; ++ i) { int k=maxnn(2,(l-1)/prime[i]+1); for(int j = k* prime[i] ; j <= r ; j += prime[i]) if(j - l >= 0) ans[j - l]=1; } for(int i = 0 ; i <= r - l ; ++ i) if(!ans[i]) tot ++; printf("%d\n" , tot); return 0; } ``` **nim游戏** ``` #include<bits/stdc++.h> using namespace std; long long tmp=0,n; int t; int main() { cin>>t; while(t--) { cin>>n; tmp=0; for(int i=1,x; i<=n; i++)cin>>x,tmp^=x; if(tmp)cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; } ```