Codeforces Round #573 Tokitsukaze, CSL and Stone Game

题目地址

Codeforces Round #573 Tokitsukaze, CSL and Stone Game
http://codeforces.com/contest/1191/problem/D

参考来源

来源于xfx的博客
https://xfx98.github.io/2019/07/13/codeforces-round-573-tokitsukaze-csl-and-stone-game/

题意

这是一道博弈题

题目给了我们两个判断条件:
1、如果有人取了石头后,剩下的石头堆中存在个数一样的石头堆,那么这个人输了。
2、如果有人要取石头的时候,没有石头了,那么这个人输了。

思路

我们先来看先手的必败态
根据条件1,如果给出的石头堆中,含有两对或者两对以上个数相同的石头堆,那么先手必输。
根据条件1,如果给出的石头堆中,有两堆或以上的石头个数相同,那么先手必输。
根据条件1,如果给出的石头堆中,有两堆或以上的石头个数是0,那么先手必输。
根据条件1,如果有一对相同的石头堆,但是存在比它石头个数小1石头堆,那么先手必输。

而如果石头个数的总和小于n * (0 + n - 1) / 2,那么必定会存在上面先手必输情况。

我们再来看操作的终态
操作的终态一定会是 0 1 2 3 …… n-1,因为任意操作都会出现两个相同堆。
这样可进行的操作次数便是 sum - n * ( n - 1 ) / 2 。然后我们根据操作次数的奇偶性即可知道谁必赢。

做法

我们先把必败态判断完,然后再去求和看操作次数的奇偶性,即可AC。

代码

c++

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; 
int a[100005];

int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 1;i <= n;i++) 
		scanf("%d", &a[i]);
	sort(a + 1, a + n + 1);
	
	int num = 0;
	for (int i = 1;i < n;i++)
		if (a[i + 1] == a[i])
			if ((a[i] == 0) || (i > 1 && a[i - 1] + 1 == a[i]) || ++num > 1)
			{
				puts("cslnb");
				return 0;
			}
			
	ll sum = 0;
	for (int i = 1;i <= n;i++) 
		sum += (ll)(a[i] - i - 1);
		
	if (sum % 2) 
		puts("sjfnb");
	else 
		puts("cslnb");
	
	return 0;
}

java

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;

public class Main {
    static StreamTokenizer st = new StreamTokenizer(new BufferedInputStream(System.in));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pr = new PrintWriter(new BufferedOutputStream(System.out));
    static Scanner sc = new Scanner(System.in);

    public static void main(String[] args) throws NumberFormatException, IOException {
        long sum = 0;
        long n = sc.nextLong();
        HashSet<Long> hs = new HashSet<>();
        ArrayList<Long> al = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            long te = sc.nextLong();
            sum += te;
            if(!hs.add(te)) {
                al.add(te);
            }
        }
        for (Long ye : al) {
            if(hs.contains(ye-1)||ye==0) {
                System.out.println("cslnb");
                System.exit(0);
            }
        }
        if (hs.size() < n - 1) {
            System.out.println("cslnb");
        } else {
            sum-=n*(n-1)/2;
            if (sum < 0) {
                System.out.println("cslnb");
            } else if ((sum & 1) == 0) {
                System.out.println("cslnb");
            } else {
                System.out.println("sjfnb");
            }
        }
    }

    private static int nextInt() {
        try {
            st.nextToken();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return (int) st.nval;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值