【2018年廣東工業大學文遠知行杯新生程式設計競賽】灰暗而空虛的景色β
http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1009&cid=832
Problem Description
In the world line 1.048596%
“雪啊。”
“雪是紅色的。”
像壞掉的復讀機一樣,梓川咲太只能把閃爍的思緒斷斷續續的說出來。
“這,是夢吧。”
從口中滑出的卻是這樣的話。
回過神的時候,天空即將被冰冷黑暗的天空吞沒,而自己已經站在湘南臺站附近的圖書館的門口。那是第一次遇見櫻島麻衣的地方,是一切的開端。
無所謂了,已經沒有可以稱為家而能回去的地方了。就在梓川咲太開始自暴自棄的躺在地上任由黑暗吞噬的時候。
眼前突然出現了穿著白大褂的年輕女子,在昏暗的路燈下,隨風飄揚的似乎是紅色的秀髮。
“不要去輕易的改變過去。”開口便是這麼難懂的話。
“打個比方,對於一個長度為n,所有元素都為0的數列。每次操作都選取一個位置,使得從這個位置往後都變成1,4,9,16...i^2 ”
“不可思議啊,為什麼我一直在,為什麼你們,一直在讓我做這種數學題。”梓川咲太快瀕臨崩潰了。
“為了拯救櫻島麻衣和牧之原翔子。這樣的理由夠充分嗎?”那位女子的一句話,讓咲太的精神從深海下看到一束光。
“你能計算出經過這麼多次操作以後變得面目全非的數列的和嗎?”
“不可隨便改變過去,就剛才那個比方來說,如果有很多次這樣的操作,那麼這個數列的和也很難計算吧。”
“可你現在就是面臨這個問題哦。計算出那個數列的和,你一定能夠知道答案。”這是隻有擁有確信的心的人才能說出來的話。
“算出來以後呢。”梓川咲太還需要最後一塊拼圖。
“去找牧之原翔子吧,一切因她而始,也必定一切因她而終。”
時間的流動在慢慢的將咲太喚回現實。
“許多失敗了的未來,無法挽回的過去,但是肯定在這之後,會有連線到......”
熟悉的話語再次傳來。但話語的主人已經消失在夜空裡。
Input
第一行輸入一個數字T(T<=10)表示資料有多少組;
每一組資料第一行包含兩個整數n(1<=n<=1e9),Q(Q<=5e4),分別表示數列的長度以及操作的個數。
接下來的Q個數按照操作的時間順序給出每次操作選擇的位置.
Output
輸出一個數字表示這個數列的和,由於答案可能很大,所以你需要將答案mod 123456789。
Sample Input
1 3 2 3 1
Sample Output
14
思路:
這道題有多次詢問,我們可以將詢問都存起來,然後倒著執行,因為後一個操作會覆蓋前面的操作因此,最後一個執行的一定沒有被覆蓋,而倒數第二個的操作,有兩種可能一是在上一個操作的區間內部,那麼我們就跳過這一次操作。二是他的操作區間比最後一次還要長,那麼這次操作區間就是,從這次的起點開始,到上一次的中點結束。就這段區間的和,就可以藉助公式了。
這裡的數會很大,因此我們需要藉助取餘操作,一開始想的是求逆元,但是發現這裡求不出逆元,後來經zxz大佬的提醒想起了另一種做法。就是可以用這個公式x/d%k=x%(d*k)/d。
ac程式碼:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<stack> #include<map> #include<string.h> #define ll long long #define ull unsigned long long #define mod 123456789 using namespace std; ll cal(ll x) { return (((x*(x+1))%(mod*6)*(2*x+1))%(mod*6))/6; } int n; int a[1010101],num[1010101]; int main() { int t; scanf("%d",&t); while(t--) { int q,n; scanf("%d%d",&n,&q); for(int i=0;i<q;i++) { cin>>a[i]; } ll ans=0,ed=n; for(int i=q-1;i>=0;i--) { if(a[i]<ed) { ans=(ans+cal(ed-a[i]+1))%mod; ed=a[i]-1; } } cout<<ans%mod<<endl; } return 0; }