【JZOJ A组】【NOIP提高A组模拟2018.8.8】没有硝烟的战争

97 篇文章 0 订阅

Description

被污染的灰灰草原上有羊和狼。有N只动物围成一圈,每只动物是羊或狼。
该游戏从其中的一只动物开始,报出[1,K]区间的整数,若上一只动物报出的数是x,下一只动物可以报[x+1,x+K]区间的整数,游戏按顺时针方向进行。每只动物报的数字都不能超过M。若一只动物报了M这个数,它所在的种族就输了。问以第i只动物为游戏的开始,最后哪种动物会赢?

Input

第一行输入三个正整数N,M,K。
接下来一行N个正整数,分别表示N只动物的种类,以顺时针的方向给出。0代表羊,1代表狼。

Output

一行输出N个整数,表示若从第i只动物开始,赢的动物的种类。同上,0代表羊,1代表狼。

Sample Input

Input 1
2 9 2
0 1
Input 2
6 499 5
1 0 0 1 1 0
Input 3
10 100 10
0 0 0 1 1 1 1 0 1 1

Sample Output

Output 1
0 1
Output 2
0 1 1 1 1 0
Output 3
1 1 1 1 1 1 1 1 1 1

Data Constraint

对于60%的数据,1 ≤ N, M, K ≤ 500。
对于100%的数据,1 ≤ N, M, K ≤ 5000。

思路

一开始以为是SG函数,结果发现根本不行(为什么不行?各位大佬肯定知道啦!),于是考虑DP

f[i][j]为第i个动物,报了j,是否有必胜策略。
预处理:f[][m]=0
对于第i只动物,当f[i+1][j+1..j+k]存在必胜策略,显然,若是同种,则f[i][j]=1,否则,f[i][j]=0反之亦然。

可是判断j+1..j+k是否存在必胜策略需要O(n)时间,所以我们要用后缀和维护。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=5077;
int n,m,k,s[maxn][maxn],f[maxn][maxn],a[maxn];
int main()
{
    freopen("vode.in","r",stdin); freopen("vode.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        f[i][m]=0;
    }
    for(int j=m-1; j>=1; j--)
    {
        for(int i=n; i>=1; i--)
        {
            if(s[i%n+1][j+1]-s[i%n+1][min(j+k,m)+1]) f[i][j]=1;
            if(a[i]!=a[i%n+1]) f[i][j]^=1;
            s[i][j]=s[i][j+1]+f[i][j];
        }
    }
    for(int i=1; i<=n; i++) printf("%d ",(s[i][1]-s[i][k+1])?a[i]:a[i]^1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值