日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[HNOI2013]数列(差分)

發布時間:2023/12/3 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [HNOI2013]数列(差分) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

[HNOI2013]數列

problem

洛谷鏈接

solution

假設每天的股價為 a[i]a[i]a[i]。則需滿足 ?i<ka[i+1]?a[i]≤m\forall_{i<k}a[i+1]-a[i]\le m?i<k?a[i+1]?a[i]m。又有參數滿足 m(k?1)<nm(k-1)<nm(k?1)<n

也就是說每天的股價都可以取到上限,即 ?i<ka[i+1]?a[i]=m\forall_{i<k}a[i+1]-a[i]=m?i<k?a[i+1]?a[i]=m

當然都要保證 a[k]≤na[k]\le na[k]n

這種每天都有增長求方案數的題目,容易聯想到差分。因為當差分數組確定時,就只與第一個元素的值有關了。

用差分刻畫數組 是很經典的套路。

?i<ks[i]=a[i+1]?a[i]\forall_{i<k}s[i]=a[i+1]-a[i]?i<k?s[i]=a[i+1]?a[i]

一個差分數組貢獻都是 111。但是有若干種股價方案的差分數組是同一個,就可以合并計算。

這里可以采用對第一天股價的起始值刻畫出差分的增值一樣但本質不同的股價方案。

顯然,方案數為 n?∑i=1k?1s[i]n-\sum_{i=1}^{k-1}s[i]n?i=1k?1?s[i]。因為在 a[1]∈[1,n?∑i=1k?1s[i]]a[1]\in[1,n-\sum_{i=1}^{k-1}s[i]]a[1][1,n?i=1k?1?s[i]] 的時候,都有 a[k]≤na[k]\le na[k]n

而本質不同的差分數列的個數又為 mk?1m^{k-1}mk?1,前面說過任何一天的增值都有可能取到 mmm

綜上可以得出答案的式子:∑j=1mk?1(n?∑i=1k?1sj[i])=nmk?1?∑j=1mk?1∑i=1k?1sj[i]\sum_{j=1}^{m^{k-1}}(n-\sum_{i=1}^{k-1}s_j[i])=nm^{k-1}-\sum_{j=1}^{m^{k-1}}\sum_{i=1}^{k-1}s_j[i]j=1mk?1?(n?i=1k?1?sj?[i])=nmk?1?j=1mk?1?i=1k?1?sj?[i]

顯然 sss 是將所有可能的合法差分數列都計算到了。并且有 sj[i]∈[1,m]s_j[i]\in[1,m]sj?[i][1,m]

先不管差分數值,那么后面一共就會有 mk?1(k?1)m^{k-1}(k-1)mk?1(k?1) 個數,并且在 [1,m][1,m][1,m] 是均勻分布。

所以 [1,m][1,m][1,m] 中的每個數出現次數都是一樣的,即 mk?2(k?1)m^{k-2}(k-1)mk?2(k?1)。在乘上數值即可。

ans=nmk?1?∑j=1mk?1∑i=1k?1sj[i]=nmk?1?∑i=1mi?mk?2(k?1)ans=nm^{k-1}-\sum_{j=1}^{m^{k-1}}\sum_{i=1}^{k-1}s_j[i]=nm^{k-1}-\sum_{i=1}^mi*m^{k-2}(k-1)ans=nmk?1?j=1mk?1?i=1k?1?sj?[i]=nmk?1?i=1m?i?mk?2(k?1)

后面的式子就是個等差數列求和而已。

最后化簡答案:ans=nmk?1?(m+1)m2mk?2(k?1)ans=nm^{k-1}-\frac{(m+1)m}{2}m^{k-2}(k-1)ans=nmk?1?2(m+1)m?mk?2(k?1)

有的題解覺得這個除法有點坑,有的用了 exgcd 求解逆元。

根本沒有這種必要啊?!

逆元是因為不能整除所以才在 ppp 域內去找有相同效果的數。

但是明顯 m(m+1)m(m+1)m(m+1) 一定有一個是偶數,一定能被 222 整除。

code

#include <bits/stdc++.h> using namespace std; #define int long long int n, m, k, p;int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % p;x = x * x % p;y >>= 1;}return ans; }signed main() {scanf( "%lld %lld %lld %lld", &n, &k, &m, &p );printf( "%lld\n", ( n % p * qkpow(m, k - 1) % p - qkpow(m, k - 2) * (k - 1) % p * (m * (m + 1) / 2 % p) % p + p ) % p );return 0; }

總結

以上是生活随笔為你收集整理的[HNOI2013]数列(差分)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。