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;
}