CF1033G 题解

CF1033G 题目传送门

目录

题意

题解

1.

2.

3.

4.

考虑先手胜利的情况:

1. 先手

2. 后手

推导范围

AC Code


题意

n 堆棋子,W 和 L 轮流取,W 每次只能取 a 个,L 每次只能取 b 个。

问,对于所有满足 a,b\in[1,m] 且 a,b\in Z(a,b),假设 W 和 L 都绝对聪明,分别有几种方案满足如下四种情况。

- W win
- L win
- 先手 win
- 后手 win


题解

1.

因为只有 W 真的是人win,所以答案是 0,m^2,0,0。做完了。

对于 (a,b):

- W win: 拿 a 的必胜
- L win: 拿 b 的必胜
- 先手 win:谁先手谁胜
- 后手 win:谁后手谁胜

显然四种情况是不会有重叠的,容易发现 W win 和 L win 的情况是等价的。

那么其实只要考虑先手必胜和后手必胜的方案数,然后就能求出所有答案。


2.

G=(v_0,v_1,...) 的局面等价于 G=(v_0 \mod(a + b),v_1 \mod(a+b),...) 的局面。好像可以解释成,分成了两个子游戏,因为这两个游戏的赢家先后手不变,所以其中有一个是 0 ,那么总的异或和不为 0
那么我们的 v_i 就会减小到 2m 以内了。


3.

草,叫起来太麻烦了……还是 A 每次拿 a
,B 每次拿 b 罢(。

我们现在只考虑先手胜还是后手胜的问题,所以我们不妨设 A 小,B 大(也就是 a \leq b
1. 情况1:v_i \in [0,a) 废点。不用管。

2. 情况2:v_i \in [a,b) A 可拿 1 次,B 拿不了。

3. 情况3:v_i \in [b,2a) A 可拿 1 次,B 拿 1 次。

4. 情况4:v_i \in[max(2a,b),a+b) A 可拿 2 次,B 拿 1 次。

我们注意到每堆最多被一个人拿。

分类讨论。被括起来的是必胜者。

(A)存在情况 2。
        不存在情况 2

  •   (A)情况 4 个数 \geq 2:那么,第一轮里, A 肯定可以和 B 抢到一个情况 4,将它转化为情况 2。

               1. 情况 4 个数 =1

               2 .情况 3 和情况 4 个数( \sum [v_i \geq b] )为奇数。

                        (A)A 是先手

                        (B)B 是先手

               3. (A)情况 3 和情况 4 个数 (\sum [v_i \geq b]) 为偶数。

不存在情况 4。

              1.  情况 3 个数 (\sum [v_i \geq b]) 是奇数

                      (A)A 是先手

                      (B)B 是先手

              2. 情况 3 个数 (\sum [v_i \geq b]) 是偶数
                      (B)A 是先手

                      (A)B 是先手

整合一下。只要考虑先手必胜和后手必胜的 (a,b)

  •  不存在情况 2    

            情况 4 个数 =1

           (先) \sum[v_i \geq b] 为奇数

  • 不存在情况 4。

>> (先):情况 3 个数 (\sum [v_i \geq b]) 是奇数

>> (后):情况 3 个数 (\sum [v_i \geq b]) 是偶数

那么我们就可以暴力枚举 O(nm^2) 了。

然鹅

过不去。。。


4.

考虑胜利的情况:

先手胜利的情况

  •  不存在 v_i \in[a,b)
  • \sum [v_i \in [\max(2a,b),a+b)]\leq 1

并且 \sum[v_i \geq b] 为奇数。

后手胜利的情况:
- 不存在 v_i \in[a,b)
\sum[v_i \in [\max(2a,b),a+b)]=0 并且 [v_i \geq b] 为偶数。

首先枚举 a+b

对 v 进行排序。

要求 a,b 就处于一个 (v_j,v_j+1] 的区间内。枚举是哪个区间。(边界区间也要考虑)

然后 \sum [v_i \geq b] 的奇偶性就可知了。分别考虑先手胜和后手胜的情况。

设最大的 vv_n,次大的是 v_{n-1}

1. 先手

  • \sum[v_i \in[\max(2a,b),a+b)]\leq 1
  •  即:\max(2a,b)>v_{n-1}
  • 即:必须满足 a> \tfrac{n_v-1}{2}和 b>v_{n-1} 中至少一个。
  • 看起来这个玩意儿需要容斥。但是实际上不用。
  • 因为 a,b 在一个区间里,所以 b>v_{n-1} 的时候 a 一定 大于 v_{n-1}>\tfrac{n_v-1}{2}。所以只需要计算 a>\tfrac{n_v-1}{2} 的情况。

2. 后手

  • \sum [v_i \in [\max(2a,b),a+b)]=0
  • 即:\max(2a,b)>v_n
  •  即:a>\tfrac{n_v}{2}b>v_n 同理。
  •  因为 a,b 在一个区间里,所以 b>v_n 的时候 a 一定大于 v_n>\tfrac{n_v-1}{2}。所以只需要计算 a>\tfrac{n_v}{2} 的情况。

推导范围

那么我们最后会框出一个 a 的范围 [l,r],然后 b \in (v_j,v_{j+1}\mod s)

l=max(v[j]%s,mx/2)+1,r=min(v[j+1]%s,m);

注意到我们开始有个设定叫 a \leq b,现在我们想抛弃它,否则会很难写。

那么就是
\min (a,b) \in [l,r],\max(a,b)\in \in (v_j,v_{j+1} \mod s)

也就是 \min(a,b) \geq l,\max(a,b) \leq r

a \geq l,b \geq l,a \leq r,b \leq r

那么最终 a 的范围就是 [\min (l,s-r),\max (r,s-l)]

AC Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls(x)((x)<<1)
#define rs(x)((x)<<1|1)
#define fi first
#define se second
#define mkp make_pair
#define PII pair<int,int>
const int N=110,M=2e5+10;
int n,m,tmp[N];
ll v[N],ans,ansf,anss;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%lld",&v[i]);
    for(int s=2;s<=(m<<1);s++)
    {
        tmp[0]=0;tmp[n+1]=s-1;
        for(int i=1;i<=n;i++)
            tmp[i]=v[i]%s;
        sort(tmp,tmp+(n+1)+1);
        for(int i=1;i<=n+1;i++)
        {
            //a,b在 [tmp[i-1],tmp[i]]之间。
            //fl: >=b 的个数是否为奇数。
            bool fl=(n+1-i)&1;
            int l=max(tmp[i-1],tmp[n-1+(!fl)]/2)+1,r=min(tmp[i],m);
            //是奇数:可能后手必败(先手必胜)。找次大
            //是偶数:可能先手必败(后手必胜)。找最大
            (fl?ansf:anss)+=max(0,min(r,s-l)-max(l,s-r)+1);
        }
    }
    ans = (1ll*m*m-ansf-anss)>>1;
    printf("%lld %lld %lld %lld\n",ans,ans,ansf,anss);
    return 0;
}



啊啊啊,一晚上的时间都耗在此题上了,中间上了厕所回来发现有个小可爱把我题解删了,亏了可以`Ctrl+Z`,不然我会气吐血的……

最后感谢老师细心地解答/纠正一些离大谱的问题/bx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值