2015沈阳赛区总结 与 简单题题解

本文是作者参加2015沈阳赛区ACM比赛后的总结,分享了比赛中遇到的博弈问题和最短路问题的解题思路,包括D题和M题。D题通过gcd判断能选取的数字范围,M题利用最短路模型解决两人相遇问题。文章还反思了比赛策略和团队合作的重要性,强调独立读题和灵活思维。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作为杭电三队,我和大三学长陈钦况,还有大一便进过WF的周贤杰组队。踏上了前往沈阳的行程。本来以平时训练的成绩,我们的期望是争金,最后却只打了个铜回来。着实是很意外,很遗憾。然而却有很多值得总结的经验和许多要吸取的教训,为我今后的比赛做准备。

比赛重现:

第20分钟,队友AC掉D题。

D题——

【题意】
共有T([1,500])组数据。
每组数据有1~n([2,20000])共n个正整数。
一开始对于已有数字集合,除了a,b(1<=a,b<=n && a≠b),其他数字都是不存在的。
对于每次成功的操作,我们是从已有数字集合之中,任选两个不同数x,y,得到z=x-y或者z=x+y,如果z是在[1,n]范围,而且z这个数字当前不存在,那我们就可以得到这个新数z,并把其放入已有数字集合之中。
Yuwgna先手,Iaka后手,谁无法操作谁就输了。问你最后的winner是谁。

【类型】
签到 博弈 gcd

【分析】
首先应该想的问题是,数轴的范围是[1,n],但是我们能选的数究竟有什么呢?
样例中的{3 1 3}{8 6 8}这样组数据,前者可以取遍1,2,3,后者却只能取得2,4,6,8,让我们很快想到实际能选取的数字范围要由gcd判定。
我们先令g=gcd(x,y),那显然我们能取的数,必然是g的倍数。
于是求出,接下来能取的数的个数num=n/g-2
所以答案就是——

【时间复杂度&&优化】
O(Tlogn)

【trick&&吐槽】
这道题之所以给了这么多样例,就是为了让这题的结论更容易观察,让这题更算得上是签到题。

【数据】
input
16
2 1 2
3 1 3
67 1 2
100 1 2
8 6 8
9 6 8
10 6 8
11 6 8
12 6 8
13 6 8
14 6 8
15 6 8
16 6 8
1314 6 8
1994 1 13
1994 7 12

output略

【代码】

int gcd(int x,int y)
{
    return y==0?x:gcd(y,x%y);
}
int main()
{
    scanf("%d",&casenum);
    for(casei=1;casei<=casenum;casei++)
    {
        int n,a,b;
        scanf("%d%d%d",&n,&a,&b);   
        printf("Case #%d: %s\n",casei,(n/gcd(a,b))&1?"Yuwgna":"Iaka");
    }
    return 0;
}

===========================================================
第50分钟,我AC掉M题。

M题——

【题意】
两个人A,B想要见面。
有n([2,1e5])个点,A初始在1点,B初始在n点。
有m个集合关系,第i个集合有Si个点,这些点两两之间移动所花费的时间都为dis([1,1e9]),有∑Si<=1e6。
让你输出A和B在哪些点碰面,使得他们能在最早时间相遇。
输出这个最早相遇时间以及所有满足的点。

【类型】
最短路

【分析】
这题很显然是一个最短路模型。然而如果暴力建边,边数可达1e12条,爆炸。
问题是怎么处理集合关系。比较好想,我读完题的瞬间就想到了做法——拆点。
对每个集合构造两个点,入点和出点,之间连一条边权为dis的边,
把集合内的每个点向这个集合的入点连边,边权为0,
把集合的出点向这个集合内的每个点连边,边权为0。
这样就实现了,对于每个集合,利用2Si+1条边,改变其内任意两个点的边权都为dis。
然后分别以1和n为起点,跑最短路,然后扫描一下即可。

【时间复杂度&&优化】
O(mlogm)

【trick&&吐槽】
点数N=n+2*最大集合数=1e5+2e6
边数M=3*最大集合数=3e6

【数据】
input
2
5 4
1 3 1 2 3
2 2 3 4
10 2 1 5
3 3 3 4 5
3 1
1 2 1 2

output
Case #1: 3
3 4
Case #2: Evil John

【代码】

const int N=1e5+2e6+10,M=3e6+10,Z=1e9+7,ms63=1061109567;
int casenum,casei;
int id;
int first[N],w[M],c[M],nxt[M];
LL f[N],F[N];
bool e[N];
struct node
{
    int x;LL v;
    node(){}
    node(
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值