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;
}