AtCoder Grand Contest 034
链接
C. Tests
直接二分答案 ,考虑最优情况下一定会让 部分取 ,否则取 。且至多只有一个数字满足 。直接枚举哪一个数字,复杂度 。
D. Manhattan Max Matching
考虑跑费用流。可以发现的一点是 ,所以直接建四个关键点,然后每个红点点 分别连 ,边权 。
蓝点同理。复杂度 ,实际上压根跑不满。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
typedef long long ll;
#define N 30010
#define M 100010
#define inf 100000000000000ll
using namespace std;
struct road{
int nxt,to,f;
ll w;
}r[M<<1];
int head[N],cnt=1;
void add(int u,int v,int f,ll w)
{
r[++cnt]=(road){head[u],v,f,w};head[u]=cnt;
r[++cnt]=(road){head[v],u,0,-w};head[v]=cnt;
}
int all=0;
ll dis[N];int pre[N],bef[N];bool in[N];
queue<int>q;
bool spfa(int s,int t)
{
for(int i=1;i<=all;i++) dis[i]=inf,pre[i]=0;
q.push(s);dis[s]=0;
in[s]=true;
while(!q.empty())
{
int u=q.front();q.pop();
in[u]=false;
for(int i=head[u];i;i=r[i].nxt)
if(r[i].f)
{
int v=r[i].to;
if(dis[v]<=dis[u]+r[i].w) continue;
dis[v]=dis[u]+r[i].w;
pre[v]=u;bef[v]=i;
if(!in[v]) q.push(v),in[v]=true;
}
}
return pre[t];
}
ll MCMF(int s,int t)
{
ll res=0;
while(spfa(s,t))
{
int w=100000000;
for(int u=t;u!=s;u=pre[u]) w=min(w,r[bef[u]].f);
res+=1ll*w*dis[t];
for(int u=t;u!=s;u=pre[u]) r[bef[u]].f-=w,r[bef[u]^1].f+=w;
}
return res;
}
int main()
{
int n;
scanf("%d",&n);
int o1=n*2+1,o2=o1+1,o3=o2+1,o4=o3+1;
int s=o4+1,t=s+1;all=t;
for(int i=1;i<=n;i++)
{
int x,y,w;scanf("%d%d%d",&x,&y,&w);
add(s,i,w,0);
add(i,o1,w,x+y);add(i,o2,w,x-y);add(i,o3,w,-x+y);add(i,o4,w,-x-y);
}
for(int i=1;i<=n;i++)
{
int x,y,w;scanf("%d%d%d",&x,&y,&w);
add(i+n,t,w,0);
add(o1,i+n,w,-x-y);add(o2,i+n,w,-x+y);add(o3,i+n,w,x-y);add(o4,i+n,w,x+y);
}
printf("%lld",-MCMF(s,t));
return 0;
}
E. Complete Compress
枚举一个根。可以发现最优情况下一定是每次移动两个不互为祖先关系的点。
考虑树形 dp, 表示 子树内处理之后所有点的深度和最小值。
特判奇偶性后直接 dp。复杂度 。
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 2010
using namespace std;
int nxt[N<<1],to[N<<1],head[N],cnt;
void add(int u,int v)
{
nxt[++cnt]=head[u];
to[cnt]=v;
head[u]=cnt;
}
int a[N];char s[N];
int f[N],siz[N];
int dfs(int u,int p)
{
siz[u]=a[u];f[u]=0;
int mx=0,mw=0;
for(int i=head[u];i;i=nxt[i])
{
int v=to[i];
if(v==p) continue;
int w=dfs(v,u);siz[u]+=siz[v];
f[u]+=f[v]+siz[v];
if(!mx || f[v]>f[mx]) mx=v,mw=w;
}
if(!mx) return 0;
return max(f[u]&1,(mw+siz[mx])-(f[u]-f[mx]-siz[mx]));
}
int main()
{
int n;
scanf("%d",&n);
scanf("%s",s+1);
for(int i=1;i<=n;i++) a[i]=s[i]=='1';
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
int ans=n*n;
for(int i=1;i<=n;i++)
if(!dfs(i,0)) ans=min(ans,f[i]);
printf("%d\n",ans>=n*n?-1:ans/2);
return 0;
}
F. RNG and XOR
考虑列方程,令 表示 到 的期望步数,显然有 。
考虑集合幂级数,即 ,处理一下即 。
直接 ,复杂度 。
#include<iostream>
#include<cstdio>
#include<cstring>
#define M 1<<18
#define mod 998244353
using namespace std;
const int inv2=(mod+1)/2;
int f[M],g[M],n,m;
int ksm(int a,int b=mod-2)
{
int r=1;
for(;b;b>>=1,a=1ll*a*a%mod) if(b&1) r=1ll*r*a%mod;
return r;
}
void fwt(int f[],int op=1)
{
for(int i=1;i<m;i<<=1)
for(int j=0;j<m;j+=i<<1)
for(int k=j;k<j+i;k++)
{
int x=f[k],y=f[i+k];
f[k]=(x+y)%mod;f[i+k]=(x-y+mod)%mod;
if(op==-1) f[k]=1ll*f[k]*inv2%mod,f[i+k]=1ll*f[i+k]*inv2%mod;
}
}
int main()
{
scanf("%d",&n);
m=1<<n;
int s=0;
for(int i=0;i<m;i++) scanf("%d",&g[i]),s=(s+g[i])%mod;
s=ksm(s);
for(int i=0;i<m;i++) g[i]=1ll*g[i]*s%mod;
g[0]--;
for(int i=1;i<m;i++) f[i]=mod-1;
f[0]=m-1;
fwt(f);fwt(g);
for(int i=0;i<m;i++) f[i]=1ll*f[i]*ksm(g[i])%mod;
fwt(f,-1);
for(int i=0;i<m;i++) printf("%d\n",(f[i]-f[0]+mod)%mod);
return 0;
}
本文来自博客园,作者:Flying2018,转载请注明原文链接:https://www.cnblogs.com/Flying2018/p/agc034.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理