Naomi's notebook

Naomi's notebook

☆数列(AGC010B - Boxes)

atcoder.jp
yutaka1999さんの問題は面白いなあ(個人的には難しいですが…)

一回の操作で、選んだ箱からN 個、他の箱から1,2,3...N-1個取る。
☆1回の操作で取られる石の個数は1/2*N(N+1)なので、何回操作を行うべきなのかがわかる(または操作によって達成できないことがわかる)。x回数行うとする。

$A_2-A_1$を$B_1$、...$A_1-A_N$を$B_N$とする。
一回の操作で、iを選んだとすると、$B_i$のみ-N+1が加算され、それ以外の$B_j$には1が加算される。
$B_1$をx回の操作で実現するためには、何回$B_1$に$1$を加算するのか計算できる。
y回とすると、$y+(-N+1)(x-y)=B_1$なので、$y=\frac{B+(N-1)x}{N}$で求められる(または実現できないことがわかる。)
これをN個について行い、矛盾がなければいい。具体的には、全てのyがx以下であり、yの合計がx*(N-1)であれば良い。
これによって達成できるか達成できないかがわかる。

long long 的な何かで2回WA
全部longlongにした方がいいですね

#include<cstdio>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<string>
#include<set>
#include<cstring>

 
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define INF 1001001001
#define LLINF 1001001001001001001
#define mp make_pair
#define pb push_back
#define LLIandI pair<long long int , int>
#define ll long long


long long int A[100004];
long long int B[100004];
ll int N;
long long sum=0;
int main(){
    scanf("%lld",&N);
    rep(i,N){
        scanf("%lld",&A[i]);
        if(i>0)B[i-1]=A[i]-A[i-1];
        sum+=A[i];
    }
    B[N-1]=A[0]-A[N-1];
    long long int X;
    if((2*sum)%(N*(N+1))==0){
        X=(long long int)(2*sum/(N*(N+1)));
    }else{
        printf("NO\n");return 0;
    }
    long long int ysum=0;
    rep(i,N){
        ll int y=(ll int)((B[i]+(N-1)*X)/N);
        if((B[i]+(N-1)*X)%N==0&&y<=X){
            ysum+=y;
        }else{
            printf("NO\n");return 0;
        }
    }
    if(ysum==X*(N-1)){
        printf("YES\n");return 0;
    }
    printf("NO\n");return 0;
}