woc day2T1太难辣。。
弃坑了。。。想看D2T1的去吉利blog
兔子与樱花:
贪心,肯定从深度大的先合并,这样影响少,然后每个点选最小的儿子。。(口胡不会证)
#include<algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <time.h> #include <vector> #include <queue> #include <map> #include <set> using namespace std; const int N=2000005; vector<int> Son[N]; int n,m,d[N],Ans,val[N]; void dfs(int u) { for(int i=0;i<Son[u].size();i++) dfs(Son[u][i]), Son[u][i]=val[Son[u][i]]; sort(Son[u].begin(),Son[u].end()); for(int i=0;i<Son[u].size();i++) if(val[u]+Son[u][i]-1<=m) val[u]+=Son[u][i]-1, Ans++; else return; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&val[i]); for(int u,i=1,k;i<=n;i++) { scanf("%d",&k); val[i]+=k; while(k--) scanf("%d",&u), Son[i].push_back(++u), d[u]=1; } for(int i=1;i<=n;i++) if(!d[i]) dfs(i); cout<<Ans<<endl; return 0; }
公约数数列:
我会分块我自豪!每块建个hash表,查询如果这段gcd都相同就在hash表里找,否则就暴力,显然gcd只会有log种,最多log次,时间复杂度$q*n^{0.5}log^2 n$跑的还很快shenmegui啊。
#include<algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <time.h> #include <vector> #include <queue> #include <map> #include <set> using namespace std; typedef long long LL; const int N=100005,Mod=357; int gcd(int a,int b) { return b?gcd(b,a%b):a; } struct H_SH { int tot,num[Mod],G[Mod],next[Mod]; void clear() { tot=0; memset(G,0,sizeof(G)); } bool operator[](int x) { int k=x%Mod; for(int i=G[k];i;i=next[i]) if(num[i]==x) return 1; return 0; } void insert(int x) { if((*this)[x]) return; int k=x%Mod; num[++tot]=x;next[tot]=G[k];G[k]=tot; } }H[Mod]; int Lzz[N],_xor[N],_gcd[N],Ed[Mod],n,q,flag,Ans,sz,K; LL x; void build(int t) { int l=Ed[t-1]+1,r=Ed[t]; H[t].clear(); H[t].insert(_xor[l]=_gcd[l]=Lzz[l]); for(int i=l+1;i<=r;i++) _gcd[i]=gcd(_gcd[i-1],Lzz[i]), H[t].insert(_xor[i]=_xor[i-1]^Lzz[i]); } void find(int t,int Lxor,int Lg) { int l=Ed[t-1]+1,r=Ed[t]; for(int i=l;i<=r;i++) if((_xor[i]^Lxor)*(LL)gcd(Lg,_gcd[i])==x) { flag=1; Ans=i; return; } } void solve() { flag=0; int Lxor=0,Lg=0; for(int i=1;i<=K;i++) { int g=gcd(Lg,_gcd[Ed[i]]); if(g!=Lg) { find(i,Lxor,Lg); if(flag) break; } else if(x%g==0&&((x/g)^Lxor)<=2000000000&&H[i][(x/g)^Lxor]) { find(i,Lxor,Lg); break; } Lxor^=_xor[Ed[i]]; Lg=g; } if(flag) printf("%d\n",Ans-1); else puts("no"); } int main() { scanf("%d",&n); sz=sqrt(n)+1; K=(n-1)/sz+1; for(int i=1;i<=n;i++) scanf("%d",Lzz+i); for(int i=1;i<=K;i++) Ed[i]=min(Ed[i-1]+sz,n), build(i); scanf("%d",&q); while(q--) { char s[10]; scanf("%s",s); if(s[0]=='M') { int x,y; scanf("%d%d",&x,&y); Lzz[++x]=y; build((x-1)/sz+1); } else scanf("%lld",&x), solve(); } return 0; }
定价:
枚举末尾0个数,算下就好
#include<algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <time.h> #include <vector> #include <queue> #include <map> #include <set> using namespace std; typedef long long LL; LL Ans,Num; LL work(LL k) { while(k%10==0) k/=10; LL w=-(k%10==5); while(k) k/=10,w+=2; return w; } void Update(LL k) { LL w=work(k); if(w<Num||(w==Num&&k<Ans)) Ans=k,Num=w; } int main() { LL t,l,r; scanf("%lld",&t); while(t--) { scanf("%lld%lld",&l,&r); Ans=l;Num=work(l); for(LL w=1;w<=r;w*=10) { LL k=l/(w*10)*(w*10); while(k<l) k+=w*10; if(k<=r) Update(k); k=l/(w*10)*(w*10)+w*5; while(k<l) k+=w*10; if(k<=r) Update(k); } cout<<Ans<<endl; } return 0; }
小Z的房间:
$Matrix-tree$定理裸上
#include<algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <time.h> #include <vector> #include <queue> #include <map> #include <set> using namespace std; typedef long long LL; const int N=15,dx[4]={1,0,-1,0},dy[4]={0,1,0,-1},Mod=1000000000; int d[N*N][N*N],id[20][20],n,m,k; #define Pr pair<int,int> #define x first #define y second Pr operator-(const Pr& A,const Pr& B) { return Pr((A.x-B.x+Mod)%Mod,(A.y-B.y+Mod)%Mod); } Pr operator*(const Pr& A,const int& B) { return Pr(A.x*(LL)B%Mod,A.y*(LL)B%Mod); } int Gauss(int n) { int flag=1; for(int i=1;i<=n;i++) { int p; for(p=i;p<=n;p++) if(d[p][i]) break; if(p!=i) { flag=-flag; for(int j=i;j<=n;j++) swap(d[i][j],d[p][j]); } for(int j=i+1;j<=n;j++) { int Lzz=d[i][i],ZZl=d[j][i]; Pr A=Pr(1,0),B=Pr(0,1); while(ZZl) swap(A,B), B=B-A*(Lzz/ZZl), swap(Lzz,ZZl), ZZl%=Lzz, flag=-flag; for (int k=i;k<=n;k++) { int Yjc=d[i][k],Cjy=d[j][k]; d[i][k]=((LL)A.x*Yjc+(LL)A.y*Cjy)%Mod; d[j][k]=((LL)B.x*Yjc+(LL)B.y*Cjy)%Mod; } } } int S=flag; for(int i=1;i<=n;i++) S=S*(LL)d[i][i]%Mod; return (S+Mod)%Mod; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { char s[15]; scanf("%s",s+1); for(int j=1;j<=m;j++) if(s[j]=='.') id[i][j]=++k; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(id[i][j]) for(int k=0;k<4;k++) { int x=i+dx[k],y=j+dy[k]; if(id[x][y]) d[id[i][j]][id[i][j]]++, d[id[i][j]][id[x][y]]--; } cout<<Gauss(k-1)<<endl; return 0; }
最短不公共子串:
出题人和yjc一样啊。。。。bfs4合1!如果要求B是子串就用后缀自动机,要求B是子序列就是一个记录$suc[a][b]$表示a后第一个字符b的位置的东西
#include<algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <time.h> #include <vector> #include <queue> #include <map> #include <set> using namespace std; const int N=2005; namespace SAM { int Son[N*2][26],pre[N*2],len[N*2],last=1,now=1; void Extend(int x) { int p=last,np=last=++now; len[np]=len[p]+1; for(;p&&!Son[p][x];p=pre[p]) Son[p][x]=np; if(!p) pre[np]=1; else { int q=Son[p][x]; if(len[q]==len[p]+1) pre[np]=q; else { int nq=++now; memcpy(Son[nq],Son[q],sizeof Son[nq]); len[nq]=len[p]+1; pre[nq]=pre[q]; pre[q]=pre[np]=nq; for(;p&&Son[p][x]==q;p=pre[p]) Son[p][x]=nq; } } } } int sucA[N][26],sucB[N][26],n,m,vis[N][N*2]; char A[N],B[N]; struct Lzz { int x,y,l; Lzz(int a=0,int b=0,int l=0):x(a),y(b),l(l){} }; int OrzLzz1() { queue<Lzz> Orz; for(int i=0;i<n;i++) Orz.push(Lzz(i,1,0)); while(!Orz.empty()) { Lzz w=Orz.front(); Orz.pop(); if(w.x==n) continue; int next=SAM::Son[w.y][A[w.x+1]-'a']; if(!next) return w.l+1; if(vis[w.x+1][next]!=1) vis[w.x+1][next]=1, Orz.push(Lzz(w.x+1,next,w.l+1)); } return -1; } int OrzLzz2() { queue<Lzz> Orz; for(int i=0;i<n;i++) Orz.push(Lzz(i,0,0)); while(!Orz.empty()) { Lzz w=Orz.front(); Orz.pop(); if(w.x==n) continue; int next=sucB[w.y][A[w.x+1]-'a']; if(!next) return w.l+1; if(vis[w.x+1][next]!=2) vis[w.x+1][next]=2, Orz.push(Lzz(w.x+1,next,w.l+1)); } return -1; } int OrzLzz3() { queue<Lzz> Orz; Orz.push(Lzz(0,1,0)); while(!Orz.empty()) { Lzz w=Orz.front(); Orz.pop(); for(int i=0;i<26;i++) { int nextx=sucA[w.x][i],nexty=SAM::Son[w.y][i]; if(!nextx) continue; if(!nexty) return w.l+1; if(vis[nextx][nexty]!=3) vis[nextx][nexty]=3, Orz.push(Lzz(nextx,nexty,w.l+1)); } } return -1; } int OrzLzz4() { queue<Lzz> Orz; Orz.push(Lzz(0,0,0)); while(!Orz.empty()) { Lzz w=Orz.front(); Orz.pop(); for(int i=0;i<26;i++) { int nextx=sucA[w.x][i],nexty=sucB[w.y][i]; if(!nextx) continue; if(!nexty) return w.l+1; if(vis[nextx][nexty]!=4) vis[nextx][nexty]=4, Orz.push(Lzz(nextx,nexty,w.l+1)); } } return -1; } int main() { gets(A+1); n=strlen(A+1); gets(B+1); m=strlen(B+1); for(int i=1;i<=m;i++) SAM::Extend(B[i]-'a'); for(int i=n-1;~i;i--) memcpy(sucA[i],sucA[i+1],sizeof sucA[i]), sucA[i][A[i+1]-'a']=i+1; for(int i=m-1;~i;i--) memcpy(sucB[i],sucB[i+1],sizeof sucB[i]), sucB[i][B[i+1]-'a']=i+1; printf("%d\n%d\n%d\n%d\n",OrzLzz1(),OrzLzz2(),OrzLzz3(),OrzLzz4()); return 0; }