8.26 Day1
爆零祭,跑8圈预定祭,被Tham D祭
T1 书堆(a)
题意:bzoj 2048
题解:可看出\(ans=m* \sum_{i=1}^{n}{\frac{1}{2i}}\)(虽然我这个物理菜狗并没有看出来)
然后有一个玄学的调和级数近似公式
\[\sum_{i=1}^{n}{\frac{1}{i}}=\ln(n)+\gamma\]
其中\(\gamma\)为欧拉常数,约等于\(0.57721566\)(背了就行)
注意这只是一个近似公式
复杂度\(O(1)\sim O(n)\)
#include<bits/stdc++.h> using namespace std; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); long long n,m,ans; long double f=0; scanf("%lld%lld",&n,&m); if(n<=1e7) for(int i=2;i<=n<<1;i+=2) f+=1.0/i; else f=(log(n)+0.5772156649)/2; ans=f*m-1e-6; printf("%lld\n",ans); return 0; }
T2 最长距离 b
题意:bzoj 1295
题解:对于每个点跑一遍spfa求出以当前点为起点符合条件的路径(即障碍物数小于等于T)
复杂度:\(O(n^2m^2+nm*spfa)\)
#include<bits/stdc++.h> using namespace std; #define mp make_pair int n,m,t,ans,G[32][32],vis[32][32],dis[32][32]; int d[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; char s[40]; queue<pair<int,int> > q; void spfa(int sx,int sy) { memset(vis,0,sizeof(vis)); memset(dis,0x7f,sizeof(dis)); vis[sx][sy]=1; dis[sx][sy]=G[sx][sy]; q.push(mp(sx,sy)); while(!q.empty()) { int tx=q.front().first,ty=q.front().second; vis[tx][ty]=0; q.pop(); for(int i=0;i<4;++i) { int tmpx=tx+d[i][0],tmpy=ty+d[i][1]; if(tmpx&&tmpy&&tmpx<=n&&tmpy<=m) { if(dis[tmpx][tmpy]>dis[tx][ty]+G[tmpx][tmpy]) { dis[tmpx][tmpy]=dis[tx][ty]+G[tmpx][tmpy]; if(!vis[tmpx][tmpy]) q.push(mp(tmpx,tmpy)),vis[tmpx][tmpy]=1; } } } } for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(dis[i][j]<=t) { int tmp=(sx-i)*(sx-i)+(sy-j)*(sy-j); if(tmp>ans) ans=tmp; } } int main() { freopen("b.in","r",stdin); freopen("b.out","w",stdout); scanf("%d%d%d",&n,&m,&t); for(int i=1;i<=n;++i) { scanf("%s",s+1); for(int j=1;j<=m;++j) G[i][j]=(s[j]=='0'?0:1); } for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) spfa(i,j); printf("%.6lf",sqrt(ans)); return 0; }
T3 聚会 c
题意:bzoj 1832
题解:一开始以为是个图就自闭了,后面突然发现是棵树然后赶紧写掉,结果分类讨论写挂了直接枚举lca即可
复杂度:\(O(n\log n)\)
#include<bits/stdc++.h> using namespace std; #define maxn 500005 struct Edge { int fr,to; }eg[maxn<<1]; int head[maxn],edgenum,n,m,deep[maxn],fa[maxn][20],ln; inline void add(int fr,int to) { eg[++edgenum]=(Edge){head[fr],to}; head[fr]=edgenum; } inline void dfs(int rt,int fat,int dep) { deep[rt]=dep; fa[rt][0]=fat; for(int i=head[rt];i;i=eg[i].fr) if(eg[i].to!=fat) dfs(eg[i].to,rt,dep+1); } inline int lca(int x,int y) { if(deep[x]<deep[y]) swap(x,y); int dist=deep[x]-deep[y]; for(int i=0;i<=ln;++i) if((1<<i)&dist) x=fa[x][i]; if(x==y) return x; for(int i=ln;i>=0;--i) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } inline int getdis(int x,int y) { return deep[x]+deep[y]-2*deep[lca(x,y)]; } int main() { freopen("c.in","r",stdin); freopen("c.out","w",stdout); scanf("%d%d",&n,&m); int a,b,c; for(int i=1;i<n;++i) { scanf("%d%d",&a,&b); add(a,b),add(b,a); } dfs(1,0,0); ln=log(n)/log(2)+1; for(int i=1;i<=ln;++i) for(int j=1;j<=n;++j) fa[j][i]=fa[fa[j][i-1]][i-1]; for(int i=1;i<=m;++i) { scanf("%d%d%d",&a,&b,&c); int l1=lca(a,b),l2=lca(a,c),l3=lca(b,c); if(l1==l2) printf("%d %d\n",l3,getdis(l3,a)+getdis(l3,b)+getdis(l3,c)); else if(l1==l3) printf("%d %d\n",l2,getdis(l2,a)+getdis(l2,b)+getdis(l2,c)); else if(l2==l3) printf("%d %d\n",l1,getdis(l1,a)+getdis(l1,b)+getdis(l1,c)); } return 0; }
T4 地精部落 d
题意:bzoj 1925
题解:神仙dp。题解直接度娘吧。代码奇短好评
复杂度:\(O(n^2)\)
#include<bits/stdc++.h> using namespace std; #define maxn 5005 int dp[maxn][maxn]; int main() { int n,mod,ans=0; scanf("%d%d",&n,&mod); dp[1][1]=dp[2][2]=1; for(int i=3;i<=n;++i) { for(int j=2;j<=i;++j) dp[i][j]+=dp[i][j-1]+dp[i-1][i-j+1],dp[i][j]%=mod; } for(int i=2;i<=n;++i) ans+=dp[n][i],ans%=mod; ans<<=1; ans%=mod; printf("%d\n",ans); return 0; }
T5 纪念品盒 e
题意:bzoj 4368
题解:贪心。也是度娘吧。
复杂度:\(O(n)\)
#include<bits/stdc++.h> using namespace std; #define maxn 10000005 int l[maxn],r[maxn],pos[maxn],n,k,L; long long LL[maxn],RR[maxn]; int main() { freopen("e.in","r",stdin); freopen("e.out","w",stdout); scanf("%d%d%d",&n,&k,&L); for(int i=1;i<=n;++i) scanf("%d",&pos[i]); int lenl=0,lenr=0; for(int i=1;i<=n;++i) { if(!pos[i]) continue; if((pos[i]<<1)<=L) l[++lenl]=pos[i]; else r[++lenr]=pos[i]; } for(int i=1;i<=lenr>>1;++i) swap(r[i],r[lenr-i+1]); for(int i=1;i<=lenl;++i) { if(i<=k) LL[i]=l[i]<<1; else LL[i]=LL[i-k]+(l[i]<<1); } for(int i=1;i<=lenr;++i) { if(i<=k) RR[i]=(L-r[i])<<1; else RR[i]=RR[i-k]+((L-r[i])<<1); } long long ans=LL[lenl]+RR[lenr]; for(int i=0;i<k;++i) ans=min(ans,LL[lenl-i]+RR[max(0,lenr+i-k)]+L); printf("%lld\n",ans); return 0; }