AGC010 - B: Boxes

原題鏈接

題意簡述

給出一個由n(n105) 個數構成的環,每次可以選擇一個位置並從這個數起順時針依次對每個數-1,-2,-3,…,-n。問能否將所有數全變爲0。

分析

考慮一次操作對環帶來了什麼影響。
(在an 後加一個a1 來表示數環)
6,3,5,7,9(,6) -> 5,1,2,3,4(,5)
5,1,2,3,4(,5) -> 0,0,0,0,0(,0)
差分後:
3,2,2,2,3 -> 4,1,1,1,1
4,1,1,1,1 -> 0,0,0,0,0
可以看到,一次操作相當於對差分數列(或者說是差分環)的一個位置加上n-1,剩下的位置減去1。那麼只要檢查原環的差分數列能否全變爲0,並且此時和也爲0就行了。
對每一個位置的計算複雜度爲O(1) ,總時間複雜度爲O(n)

實現

每次操作會使和sum 減少 s0=n(n+1)/2 ,那麼總共進行了 k=sum/s0 次操作。如果k不爲整數那麼不可行。
差分數列的每個位置要能在數個 +(n1)1 後變爲0,否則不可行。
列式表示爲 (ai+1ai)+xi(n1)(kxi)=0 ,如果任何一個xi 不爲整數那麼不可行。
最後,如果xik 說明此時sum0 ,不可行。

代碼

#include <cstdio>
typedef long long lint;
int const N=1e5+10;
int n,a[N];
int dif[N];
int main()
{
    freopen("b.in","r",stdin);
    scanf("%d",&n);
    if(n==1) {printf("YES"); return 0;}
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    a[n+1]=a[1];
    lint s=(lint)n*(n+1)>>1,sum=0;
    for(int i=1;i<=n;i++) sum+=a[i],dif[i]=a[i+1]-a[i];
    if(sum%s!=0) {printf("NO"); return 0;}
    lint k=sum/s,sumX=0;
    for(int i=1;i<=n;i++)
    {
        lint x=(k-dif[i])/n;
        if(x<0 || x*n!=k-dif[i]) {printf("NO"); return 0;}
        sumX+=x;
    }
    if(sumX==k) printf("YES");
    else printf("NO");
    return 0;
}

注意

開longlong!int*int也有可能爆int,要先轉成longlong再乘!
連WA六發…

發佈了42 篇原創文章 · 獲贊 1 · 訪問量 8932
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章