藍橋杯:2017年第八屆藍橋杯省賽B組第十題—PREV-40K倍區間
阿新 • • 發佈:2018-11-23
膜拜這位大佬
做法:首先統計字首和sum[i] 表示A1+A2+…+Ai.所以對於任意一段區間[l,r]的和就是sum[r]-sum[l-1].如果要保證這個區間和為K倍數就是:(sum[r]-sum[l-1])%k == 0.變形後就是:sum[r]%k==sum[l-1]%k,所以我們計算字首和的時候順帶模K,然後統計字首和中相同的資料就行了。複雜度O(n).注意資料可能會溢位!!
作者:YzlCoder
來源:CSDN
原文:https://blog.csdn.net/y1196645376/article/details/69718192
巧妙地轉換成了求字首和,並找出相同值對數。需要注意的是如果字首和取模K等於0,那麼這個字首範圍就是一個K倍區間。所以找出所有相同對數後需要加上字首和等於零的個數!
線性時間找出相同對數的方法,出現一個數,加上這個數以前出現的次數,然後再讓它的出現次數加一。很巧妙的實現了當出現兩次時,記錄1次;出現三次時記錄1+2次;出現四次時記錄1+2+3次;剛好是兩兩一對得到的總和!
還需要注意的是記錄對數的變數可能溢位,須用long long int/%lld
#include<stdio.h> #include<stdlib.h> #include<stdbool.h> #define SPMAX 100005 int main(int argc,char **argv) { int cnt,k,sp[SPMAX]={0}; scanf("%d%d",&cnt,&k); int sum=0; for(int i=0;i<cnt;i++) scanf("%d",&sp[i]); sp[0]%=k; for(int i=1;i<cnt;i++) sp[i]=(sp[i]+sp[i-1])%k; int book[SPMAX]={0}; long long int ans=0; for(int i=0;i<cnt;i++) ans+=(book[sp[i]]++); printf("%lld\n",ans+book[0]); return EXIT_SUCCESS; }
這方法真的是太6啦。。666