11.18总结
T1:找规律+构造 规律挺好找的 构造有点细 还好写对了
#include<bits/stdc++.h> using namespace std; #define ll long long int n,k,st[50]; int main(){ int T;scanf("%d",&T); while(T--){ scanf("%d%d",&n,&k); if(!k){puts("YES");puts("0");continue;} if(!(k&1)){puts("NO");continue;} puts("YES"); int tot=log2(k)+1; printf("%d\n",tot); int del=((1<<tot)-1-k)>>1; memset(st,0,sizeof(st)); for(int i=0,pre=0,now=1,dlt=0;i<tot;i++){ if(del&(1<<i)) pre+=(1<<i+1),dlt+=(1<<i); else{ st[i]+=now-pre+dlt; if(dlt){ int j=0,nxt=st[i]+(1<<i),cnt=0,x=dlt; while(x) cnt++,x-=(x&-x); while(dlt) st[i-cnt+j]=nxt-(dlt&-dlt),dlt-=(dlt&-dlt),nxt=st[i-cnt+j],j++; } }now+=(1<<i); }for(int i=0;i<tot;i++) printf("%d ",st[i]); puts(""); }return 0; }
T2:最短路 为多个关键点找最近关键点
考场上直接想成二进制分组了(见过一道类似的题目),然后光荣TLE30
正解是一遍dij后记录每个点被哪个关键点更新,然后枚举每条边更新答案即可

#include<bits/stdc++.h> using namespace std; #define N 300005 #define M 500005 #define P pair<int,int> #define fi first #define se second #define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) char buf[1<<21],*p1=buf,*p2=buf; inline int rd(){ int x=0,f=1;char c=gc(); for(;c>'9'||c<'0';c=gc()) if(c=='-') f=0; for(;c>='0'&&c<='9';c=gc()) x=x*10+c-48; return f?x:-x; }int n,lst[N],st[M<<1],ed[M<<1],nxt[M<<1],len[M<<1],tot,m,k,id[N],dis[N],vis[N],ans[N],f[N]; inline void add_e(int x,int y,int z){ed[++tot]=y,st[tot]=x,nxt[tot]=lst[x],lst[x]=tot,len[tot]=z;} priority_queue<P,vector<P>,greater<P> >q; inline void dijkstra(int x){ memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); for(int i=1;i<=k;i++) q.push(P(0,id[i])),dis[id[i]]=0; while(!q.empty()){ int u=q.top().se;q.pop(); if(vis[u]) continue;vis[u]=1; for(int i=lst[u];i;i=nxt[i]){ if(!vis[ed[i]]&&dis[ed[i]]>dis[u]+len[i]){ dis[ed[i]]=dis[u]+len[i]; if(f[ed[i]]!=ed[i]) f[ed[i]]=f[u]; q.push(P(dis[ed[i]],ed[i])); } } } }int main(){ n=rd(),m=rd(),k=rd(); memset(ans,0x3f,sizeof(ans)); for(int i=1;i<=m;i++){ int x=rd(),y=rd(),z=rd(); add_e(x,y,z);add_e(y,x,z); }for(int i=1;i<=k;i++) f[id[i]=rd()]=id[i]; dijkstra(1); for(int i=1;i<=tot;i+=2){ if(f[st[i]]==f[ed[i]]) continue; int d=dis[st[i]]+len[i]+dis[ed[i]]; ans[f[st[i]]]=min(ans[f[st[i]]],d); ans[f[ed[i]]]=min(ans[f[ed[i]]],d); }for(int i=1;i<=k;i++) printf("%d ",ans[id[i]]==0x3f3f3f3f?-1:ans[id[i]]); return 0; }
T3:字符串哈希 本来应该能过的 毕竟已经非常接近正解了 只是脑子出了点问题
没有考虑到拿较长串的哈希值相减,而是拿较短串的哈希值加上拼接段,复杂度就变成了20000方乘上log,TLE70

#include<bits/stdc++.h> using namespace std; #define N 2005 #define M 20005 #define mod 998244353 #define ll long long #define sd 131 int n,m,p,q,r;char s[M][N],t[M][N]; ll ht[M],hd[M],hs[M],ans,pw[N];unordered_map<ll,int>mp; inline void Hsh(int x){ ll t1=1,h1=0; for(int i=1;i<=r-q;i++) (t1*=sd)%=mod; for(int i=1;i<=q;i++) (h1+=t1*t[x][i]%mod)%=mod,(t1*=sd)%=mod; ht[x]=h1; }inline void hshd(int x){ ll t1=1,h1=0; for(int i=r+1;i<=p;i++) (h1+=t1*s[x][i]%mod)%=mod,(t1*=sd)%=mod; hd[x]=h1; }inline void hsh(int x,int y){ ll t1=1,h1=0; for(int i=y;i<=r;i++) (h1+=t1*s[x][i]%mod)%=mod,(t1*=sd)%=mod; for(int i=1;i<y;i++) (h1+=t1*s[x][i]%mod)%=mod,(t1*=sd)%=mod; hs[x]=h1; }int main(){ scanf("%d%d%d%d",&n,&m,&p,&q);r=(p+q)>>1; for(int i=1;i<=n;i++) scanf("%s",s[i]+1); for(int i=1;i<=m;i++) scanf("%s",t[i]+1); for(int i=1;i<=m;i++) Hsh(i); for(int i=1;i<=n;i++) hshd(i);pw[0]=1; for(int i=1;i<=r;i++) pw[i]=pw[i-1]*sd%mod; ll inv=922042494; for(int j=1;j<=m;j++) mp[ht[j]]++; for(int i=1;i<=n;i++){ ll lst=-1;hsh(i,1); for(int j=1;j<=r;j++){ if(lst!=hs[i]) ans+=mp[(hs[i]+mod-hd[i])%mod]; lst=hs[i]; (hs[i]+=mod-s[i][j])%=mod; (hs[i]+=s[i][j]*pw[r]%mod)%=mod; (hs[i]*=inv)%=mod; } }printf("%lld",ans); return 0; }
T4:找找规律,很容易发现只有选择一条权值全为1的链或两段1由一个2连接可能成为最优答案(若无权为1的点就直接选权值最小即可) 简单换根dp 考场上没怎么看啧

#include<bits/stdc++.h> using namespace std; #define N 1000005 #define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) char buf[1<<21],*p1=buf,*p2=buf,pt[1005],Z; inline int rd(){ int x=0,f=1;char c=gc(); for(;c>'9'||c<'0';c=gc()) if(c=='-') f=0; for(;c>='0'&&c<='9';c=gc()) x=x*10+c-48; return f?x:-x; }int n,lst[N],ed[N<<1],nxt[N<<1],val[N],tot,f[N],mx[N],se[N],ans,ans1; inline void add_e(int x,int y){ed[++tot]=y,nxt[tot]=lst[x],lst[x]=tot;} void dfs(int x,int fa){ for(int i=lst[x];i;i=nxt[i]){ if(ed[i]==fa) continue; dfs(ed[i],x); if(f[ed[i]]>mx[x]) se[x]=mx[x],mx[x]=f[ed[i]]; else if(f[ed[i]]>se[x]) se[x]=f[ed[i]]; }if(val[x]==1){ f[x]=mx[x]+1; ans=max(ans,f[x]+se[x]); } }void dfs1(int x,int fa){ if(x!=1){ int tmp=mx[fa]+1; if(f[x]==mx[fa]) tmp=se[fa]+1; if(mx[x]<tmp) se[x]=mx[x],mx[x]=tmp; else if(se[x]<tmp) se[x]=tmp; f[x]=mx[x]+1; }if(val[x]==2) if(mx[x]==se[x]) ans1=max(ans1,mx[x]+se[x]+1); for(int i=lst[x];i;i=nxt[i]){ if(ed[i]==fa) continue; dfs1(ed[i],x); } }int main(){ n=rd(); for(int i=1;i<n;i++){ int x=rd(),y=rd(); add_e(x,y);add_e(y,x); }int mn=0x3f3f3f3f; for(int i=1;i<=n;i++) val[i]=rd(),mn=min(mn,val[i]); if(mn>1) return printf("%d/1\n",mn),0; dfs(1,0);dfs1(1,0); if(ans*2>=ans1) printf("1/%d",ans); else printf("2/%d",ans1); return 0; }

浙公网安备 33010602011771号