AtCoder Grand Contest 010 B - Boxes 验证解的存在性 2017/2/6

题意:给定N个围成一圈的数,重复进行下述操作: 挑选第i个数,从i+1转一圈回到i,依次减去1到N。 问是否存在一种操作使得最后整圈的数全为0。

解题方法: 逆向思维好题! 将该过程倒着来看,就是每轮选择第i个数,从i+1转一圈回到i,依次加上1到N,将该操作设为操作1。问最后能否加到给定数列。令d[i]=a[i]-a[i-1],即考虑前数与后数之间的差,会发现,每次进行操作1时,差分的改变要么+1,要么-N+1,且两种情况里都有+1。故将差分减去s(操作的轮数),即处理掉+1的影响后。-N出现的次数恰为操作的轮数。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 100010;
LL a[maxn];
LL sum;
int main()
{
    LL n;
    scanf("%lld", &n);
    for(int i = 1; i <= n; i++){
        scanf("%lld", &a[i]);
        sum += a[i];
        a[i-1] = a[i] - a[i-1];
    }
    a[0] = a[0] - a[n];
    if(n == 1){
        printf("YES\n");
        return 0;
    }
    if((sum*2)%(n*(n+1))){
        printf("NO\n");
        return 0;
    }
    LL ans = 0;
    LL cnt = sum / (n*(n+1)/2);
    for(int i = 0; i < n; i++){
        a[i] -= cnt;
        if(a[i] % n || a[i] > 0){
            printf("NO\n");
            return 0;
        }
        ans += a[i] / (-n);
    }
    if(cnt == ans){
        printf("YES\n");
    }
    else{
        printf("NO\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值