时间限制: 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;
}