AtCoder Grand Contest 033
链接
A. Darker and Darker
B. LRUD Game
C. Removing Coins
博弈论结论题。首先硬币多少没有关系,所以题面就变成选择一个点,然后删去以它为根时的叶子节点。
可以发现,无论选取哪一个点都会导致直径至少减少1。如果选取了非直径端点的点则会导致直径减少2。
显然当直径等于 0 时没有点可以选。也就是说,除了最后一步之外,两个人都可以选择直径 -2 或 -1。
最后一步有可能只存在两个点,这种情况下只能一个个选。也就是说 2 是先手必败。
这样就可以推出,假如长度除 3 的余数等于 0 或 1,那么先手把长度取为 2,然后取 3-后手选择的数字 即可。
反之后手必胜。
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 200010
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;
}
void dfs(int u,int p,int &t,int &l)
{
t=u;l=1;
for(int i=head[u];i;i=nxt[i])
{
int t1=0,l1=0,v=to[i];
if(v==p) continue;
dfs(v,u,t1,l1);
if(l1+1>l) l=l1+1,t=t1;
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
int t=0,l=0;
dfs(1,0,t,l);
dfs(t,0,t,l);
puts(l%3==2?"Second":"First");
return 0;
}
D. Complexity
E. Go around a Circle
首先考虑钦定第一个是红的,否则翻转红蓝结果一定不变。
然后如果所有都是红的,那么结果就是不能有一个点连出两条蓝边,直接递推即可。
否则仍然还是不能有一个点连出两条蓝边,同时两个蓝边之间至少的红边数为奇数。
考虑连续的 的最小值,可以发现任何两个蓝边之间的红边数不能大于这个值。然后按照这两个条件 dp 即可,加上前缀和优化。
复杂度 。
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 200010
#define mod 1000000007
using namespace std;
int f[N],a[N],nxt[N];
char s[N];
int ksm(int a,int b=mod-2)
{
int r=1;
for(;b;b>>=1)
{
if(b&1) r=1ll*r*a%mod;
a=1ll*a*a%mod;
}
return r;
}
int main()
{
int n,m;
scanf("%d%d%s",&n,&m,s+1);
for(int i=1;i<=m;i++) a[i]=s[i]==s[1];nxt[m+1]=m+1;
for(int i=m;i;i--) nxt[i]=a[i]?nxt[i+1]:i;
if(nxt[1]==m+1)
{
f[0]=1,f[1]=2;
for(int i=2;i<=n;i++) f[i]=(f[i-1]+f[i-2])%mod;
if(n==1) puts("1");
else if(n==2) puts("3");
else printf("%d\n",(f[n-1]+f[n-3])%mod);
return 0;
}
if(n&1){puts("0");return 0;}
int t=nxt[1];
for(int i=1;i<=m;i++)
if(nxt[i]!=m+1 && !a[i-1] && (nxt[i]-i)%2) t=min(t,nxt[i]-i);
n=n/2,t=(t+1)/2;
int v=0;
for(int i=1;i<=n;i++)
{
if(i>t) f[i]=v=(v-f[i-t-1]+mod)%mod;
else f[i]=(v+i*2)%mod;
v=(v+f[i])%mod;
}
printf("%d\n",f[n]);
return 0;
}
F. Adding Edges
考虑如果最后的三个点 是有序的,那么我们可以处理依次加入一条边。
然后考虑记 表示以 为根 有连边的最近的祖先。对于每一条边 :
如果 那么不用加入。否则如果 存在那么加入 。
否则我们暴力 dfs 的整颗子树让所有点的父亲指向 ,对于 同理,然后再加入 。
然后对于统计答案直接统计每个点为根时与其他点是否有边即可。
复杂度 。
本文来自博客园,作者:Flying2018,转载请注明原文链接:https://www.cnblogs.com/Flying2018/p/agc033.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编程运行原理