Boxes

时间限制: 2 Sec  内存限制: 256 MB
 

题目描述

There are N boxes arranged in a circle. The i-th box contains Ai stones.

Determine whether it is possible to remove all the stones from the boxes by repeatedly performing the following operation:

Select one box. Let the box be the i-th box. Then, for each j from 1 through N, remove exactly j stones from the (i+j)-th box. Here, the (N+k)-th box is identified with the k-th box.
Note that the operation cannot be performed if there is a box that does not contain enough number of stones to be removed.

Constraints
1≤N≤105
1≤Ai≤109

输入

The input is given from Standard Input in the following format:

N
A1 A2 … AN

输出

If it is possible to remove all the stones from the boxes, print YES. Otherwise, print NO.

样例输入

5
4 5 1 2 3

样例输出

YES

提示

All the stones can be removed in one operation by selecting the second box.

 

 

题意很简单,给你n个盒子围成一圈,对于第i个盒子里面有ai个石头,

一步操作——选择其中一个盒子,从它后面一个盒子开始,依次取1,2,3....n个石头(对于标号大于n,例如n+1,则看成第1个盒子)。

现在问,能否进行不限次操作,使得每个盒子全部取空。

 

思路1

以n=5为例,容易看出,

1,2,3,4,5

5,1,2,3,4

4,5,1,2,3

3,4,5,1,2

2,3,4,5,1

取其中的任意一个或多个(也可以取多个相同序列)叠加都可以

那么,扩展到n个则有矩阵(xi,表示第i个序列取的次数)

1,2,3,4,5................n                                        x1

n,1,2,3,4..........n-1                                       x2

n-1,n,.......,n-2                                       x3

..................................                    ×                  ..                                    =输入的矩阵

..................................                                        ...

2,3,4,5.............n,1                                        xn

 

然后找规律。。

 

 

思路2

 

对于每一个序列来说,a(i+1)-ai等于1或1-n

例如5,1,2,3,4

相差不是1就是-4(1-5)

 

若能取完,则说明(a1+a2+...an)%(1+2+3+...n)=0

也就是说最多进行    k=(∑ai(1<=i<=n))/((1+n)*n/2)    次操作

那么对于叠加后的有

((a(i+1)-ai)+k*(n-1))%n=0

 

对于(a(i+1)-ai)=k*1,原式=k*n,符合

对于(a(i+1)-ai)=k*(1-n),原式=0,符合

对于1,1-n,混杂的,1+(n-1)=n,(1-n)+n-1=0,原式=x*n(x<k),依旧符合

 

最后加上一个1的个数是n-1的个数n-1倍判断问题解决

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <map>
#define pi acos(-1.0)
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3fLL
#define ms(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
int minn(int a,int b,int c){return min(min(a,b),c);}
int maxx(int a,int b,int c){return max(max(a,b),c);}
int gcd(int x, int y){if(y==0)return x;return gcd(y, x%y);}
 

ll n, a[200005];
int main()
{
    ll i, sum=0, flag=1, x=0, y=0;
    scanf("%lld", &n);
    for(i=0;i<n;i++){
        scanf("%lld", &a[i]);
        sum+=a[i];
    }
    ll tmp=n*(n+1)/2;
    if(sum%tmp){
        printf("NO\n");
        return 0;
    }
    ll cot=sum/tmp, d, dd;
    for(i=0;i<n;i++){
        if(i)
            d=a[i]-a[i-1];
        else
            d=a[i]-a[n-1];
 
        d+=cot*(n-1);
 
        if(d%n!=0){
            printf("NO\n");
            return 0;
        }
 
        dd=d/n;
 
        if(dd<0 || dd>cot){//取多少次,小于0的和大于cot的都不符合
            printf("NO\n");
            return 0;
        }
 
        x+=dd;//1的个数
        y+=(cot-dd);//n-1的个数
 
    }
    if(x==y*(n-1))
        printf("YES\n");
    else
        printf("NO\n");
 
    return 0;
}

 

 

 

思路3(超时)

 

因为给定的是叠加的,所以最大的那个ai为起点,向后模拟操作取走石头,再次找最大的,以此类推

然后超时了

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <map>
#define pi acos(-1.0)
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3fLL
#define ms(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
int minn(int a,int b,int c){return min(min(a,b),c);}
int maxx(int a,int b,int c){return max(max(a,b),c);}
int gcd(int x, int y){if(y==0)return x;return gcd(y, x%y);}
 
ll a[100005];
ll b[100005];
int flag;
int main()
{
    ll n;
    scanf("%lld",&n);
 
    ll maxx=0,maxi=0;
 
    for(ll i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        if(a[i]>maxx)
            maxx=a[i],maxi=i;
    }
 
    while(1)
    {
        ll count=0;
        ll maxj,maxjx;
 
        a[maxi]-=n;
 
        if(!a[maxi])count++;
 
        maxj=maxi,maxjx=a[maxi];
 
        for(ll i=1;i<n;i++)
        {
            ll t=i+maxi;
            if(t>n)
                t-=n;
            a[t]-=i;
 
            if(maxjx<a[t])
                maxjx=a[t],maxj=t;
 
            if(!a[t])
                count++;
            else if(a[t]<0)
            {
                flag=1;
                break;
            }
        }
        if(flag)
            break;
        if(count==n)
            break;
        maxi=maxj,maxx=maxjx;
    }
 
    if(flag)
        printf("NO\n");
    else
        printf("YES\n");
 
 
    return 0;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值