待更新
鏈接:https://www.nowcoder.com/acm/contest/117/B
來源:牛客網
時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
題目描述
ATG5是ATG系列最新作,遊戲故事發生以美國洛杉磯及其周邊地區爲原型的城市Sos Lantos,是現實地區中的洛杉磯和南加州。製作單位拍攝了超過25萬張相關照片,並且研究了人口調查和汽車銷售數據,以建立遊戲中的世界。
ATG系列歷來都是以黑幫生活爲背景的知名動作冒險遊戲。主人公自然與黑道脫不了干係,在ATG5中游戲元素將會得到增強,加入了更加開放自由的世界,以故事驅動,以任務爲準的遊戲玩法和多人模式。故事主題聚焦金錢永不眠的南加利福尼亞。這次作品是有史以來最具活力的和最多元化的開放式世界,作爲玩家可以反覆進入三個角色的生活,玩交織在一起的所有內容。
ATG5這款遊戲質量很高,但是外掛猖獗。。。
最近,三七開發現了一款神奇的外掛,可以讓他在多個賬號之間轉移金錢。
神奇外掛的神奇不止於此,當他把一個賬號的金錢轉移到另一個賬戶時,原來賬戶裏的金錢並不會減少!是不是很神奇?
三七開一共有n個賬號,每一天他都會通過這個神奇外掛把第1個賬號的金錢“轉移”到第2個賬號,再把第2個賬號的金錢“轉移”到第3個賬號,……,再把第n-1個賬號的金錢“轉移”到第n個賬號。
但是三七開忘了一件事情,遊戲中金錢數量是有上限的,每當一個賬號的金錢數大於等於1000000007(=1e9+7)時,這個賬號的金錢數就會對1e9+7取模,即變成金錢數除以1e9+7的餘數。儘管如此,三七開還是很開心地繼續使用着他的神奇外掛,並且沒有花賬號裏的一分金錢。
然而,在三七開使用了k天神奇外掛之後,B星公司(ATG5的發行公司)發現了他的開掛行爲。B星公司對使用外掛行爲非常仁慈,決定不對三七開進行封號處理,而是將三七開的所有賬號的金錢數恢復至他開掛以前的數值。但服務器並沒有關於那麼久遠的數據的存檔,只有現在的金錢數的數據,以及檢測到的開掛天數k。
你能幫助B星公司恢復三七開的賬號數據嗎?
輸入描述:
第一行是一個正整數T(T ≤ 15),表示測試數據的組數,
對於每組測試數據,
第一行包含兩個整數n(2 ≤ n ≤ 1000),k(0 ≤ k ≤ 100000000),表示賬號個數和開掛天數,
第二行包含n個小於1e9+7的非負整數,第i個整數表示當前第i個賬號的金錢數。
輸出描述:
對於每組測試數據,輸出一行,包含n個以空格分隔的非負整數(每個數範圍小於109+7,注意不要有行末空格),第i個整數表示開掛前第i個賬號的金錢數。
示例
輸入
2
3 1
3 2 1
4 2
1 2 1 2
輸出
3 1000000006 1000000006
1 0 1000000005 2
解題思路:
一:
dp數組表示之前未使用外掛之前的每個帳號的金錢數
假設第一個賬號金錢數爲x,其他都爲0;
則得到下圖:表示在第i天第j個帳號的金錢數
i\j | 1 | 2 | 3 | 4 | 5 | 6 | 7 | … | n |
---|---|---|---|---|---|---|---|---|---|
0 | x | 0 | 0 | 0 | 0 | 0 | 0 | … | |
1 | x | x | x | x | x | x | x | … | |
2 | x | 2x | 3x | 4x | 5x | 6x | 7x | … | |
3 | x | 3x | 6x | 10x | 15x | 21x | 28x | … | |
4 | x | 4x | 10x | 20x | 35x | 56x | 84x | … | |
… | … | … | … | … | … | … | … | … | |
k | x | k*x | [(k+1)*k/2]x | [(k+2)*(k+1)*k/6]x | … | … | … | … | [(k+n-2)(k+n-1)*…*k/(n-1)!]x |
由圖可知,第一個帳號的金錢數x不變,而其他的由(本金)和(左邊帳號的值)組成,即dp[ i ][ j ]=dp[ i -1 ][ j ]+dp[ i ][ j - 1 ];觀察當i==k(即第k天)時帳號的金錢,可得出當j==n時,帳號的金錢數爲 。這是當第一天第一個帳號金錢數爲x,而其他帳號均爲零的情況,即反映了一個帳號對其後帳號金錢數的影響。
設每個帳號初始值爲init[ i ],即
v[1] 不變
v[2]=init[1]的影響+init[2]
v[3]=init[1]的影響+init[2]的影響+init[3]
v[4]=init[1]的影響+init[2]的影響+init[ 3 ]的影響+init[4]
······
v[n]=init[1]的影響+init[2]的影響+······+init[n-1]的影響+init[n]
公式化即
v[n]= * init[1] + * init[2] + … + *init[n-1] + *init[n]
因爲v[1]=init[1];知道了init[1]的值,可以一步步求解每個帳號的初始值;
二:
還有一點需要注意,即題中給你的並不是每個帳號的實際金錢數,而是對1e9+7取模過的值;
即 v[2] = ( *init[1]+init[2])% mod ;因爲init[2] < mod,
所以原式=(( *init[1])) % mod +init[2]) % mod ;
分兩種情況:
<1>:(( *init[1])) % mod +init[2])< mod ;
init[2] = v[2] -( *init[1])) % mod ;
<2>:(( *init[1])) % mod +init[2])>= mod ;
init[2] = v[2] + mod -( *init[1])) % mod ;
因爲這兩種情況只有一個成立,所以兩個方程解出來的一定有一個是合法的解。
三:
接下來是組合數取模,需要用到乘法逆元,對於此題可以用 費馬小定理 來把除法轉化爲乘法
%mod = % mod
= * % mod
= * % mod
= % mod }*{ % mod }
式子的前半部分直接求,後半部分可以用快速冪,因爲值都要使用多次,可以算一遍存在數組裏;即兩個數組:
<1> kn[ i ] 表示 (k-1+i-1) * (k-1+i-2) * … *(k-1+1) % mod ;
<2> nn[ i ] 表示 % mod ;
再利用步驟二中的式子求解即可;