51nod1680 區間求和(BIT dp)

2021-08-15 07:10:26 字數 1328 閱讀 6069

有n個數,給定乙個k,求所有長度大於等於k的區間中前k大數的總和。這樣就比較簡單相信大家都會,所以此題要求當k=1~n的總和,即求∑n

k=1∑

n−k+

1i=1

∑nj=

i+k−

1  區間前k大和

input

輸入五個數n,a1,a,b,c。a1表示第乙個數,a,b,c用來生成其餘n-1個數。a(i)=(a(i-1)*a+b)mod c。1<=n<=1,000,000,0<=a1,a,b,c<=1,000,000,000
output

乙個數表示答案,最後答案對1,000,000,007取模。
input示例

3 3 1 1 10
output示例

63

樣例解釋:

三個數為3,4,5

k=1:[1,1]=3,[1,2]=[2,2]=4,[1,3]=[2,3]=[3,3]=5(表示各個區間在k=1時的答案)

k=2:[1,2]=7,[2,3]=[1,3]=9

k=3:[1,3]=12

題意:求出所有區間前1大,前2大,前3大...前n大的數的和,當然前提是某個區間有足夠的數。

思路:考慮[l,r]區間的前1大~前r-l+1大的數之和為ans1,轉移到區間[l,r+1],

它的ans2就是ans2=ans1+(x+1)*a[r+1]+y,

其中x是[l,r]小於等於a[r+1]的數量,y是[l,r]大於a[r+1]的數的和,畫圖模擬下就知道了。

令dp[i]為所有右界為i的區間的ans,那麼對於[1,i-1]中小於等於a[i]的數a[j],顯然貢獻了j次;

對於[1,i-1]中大於a[i]的數a[k],貢獻了a[k]*k次,最後加上a[i]自己貢獻了一次。

這些值離散化後用bit維護即可。

# include using namespace std;

typedef long long ll;

const int maxn = 1e6+3;

const ll mod = 1e9+7;

ll a[maxn+3], b[maxn+3], s[2][maxn+3], dp[maxn];

void update(int pos, ll val, int id)

}ll cal(int pos, int id)

return res;

}int main()

for(int i=1; i<=n; ++i)

printf("%lld\n",ans);

return 0;

}

51nod 1712 區間求和

解法 這個題首先考慮乙個簡單情況 對於區間 x,y 權值為多少。容易寫出公式 f x y s y s x 1 sum y sum x 1 x 1 sum x 1 y x 1 其中s x 表示 從第乙個元素到第x個元素的 所有有序二元組的和 題目中定義的 sum表示字首和 這裡要求的是所有a x a ...

51nod 1690 區間求和2

給出乙個長度為n的陣列a。區間 l,r 的值為 r li 0a l i a r i 求所有長度為質數的區間的值的總和。很容易想到,列舉乙個數對,然後統計他的答案 比如說,我們列舉了乙個數對 i j i,j 那麼他的答案的貢獻會有兩種情況 1.i j n 1 i j n 1這個的話,能包含他的區間長度...

51nod 1690 區間求和2

一開始考慮的是對於每個a ia i ai 有哪些a ja j aj 與它相乘,但是這樣做不了。正解是考慮每對 ai aj a i,a j ai a j 的貢獻,然後用fft優化。首先直接把長度為2 22的給算了,然後剩下的都是奇質數長度。預處理s is i si 表示1 11 i ii有多少個奇質數...