1. 程式人生 > >牛客練習賽42D(性質、數學)

牛客練習賽42D(性質、數學)

iostream 題解 數學計算 出現 nbsp for pac urn 補丁

題目傳送

就像題解所說的,寫幾個可以發現有分成四段的性質:第一段是從n開始往下貪,第二段是個數字,第三段……臥槽好吧真難描述。

然後發現這個數據量可達1e9,所以考慮“二分確定序列+數學計算”的方式解題。

首先二分出第一段的長度,這裏我寫得醜了,又將某些情況特判了一下;不難發現有了第一段的長度、N、K這三個量,序列已確定。

然後瘋狂手推數學公式把這四段的值求出來,特殊情況的例子很好舉,自己調一調打打補丁做一做膜法,大概就莽A了吧……不過要是在考場上本垃圾就必死無疑了。

 1 #include <cstdio>
 2
#include <cmath> 3 #include <iostream> 4 using namespace std; 5 6 typedef long long ll; 7 const ll mod = 1e9 + 7; 8 ll N, K, x, ans1, ans2, ans3, ans4; 9 10 ll add(ll a, ll b) { 11 return a + b >= mod ? a + b - mod : a + b; 12 } 13 14 ll sub(ll a, ll b) { 15
return a - b < 0 ? a - b + mod : a - b; 16 } 17 18 ll ksm(ll a, ll b) { 19 ll ret = 1; 20 for (; b; b >>= 1) { 21 if (b & 1) ret = ret * a % mod; 22 a = a * a % mod; 23 } 24 return ret; 25 } 26 27 inline ll cal(ll l, ll r) { 28 return
(l + r) * (r - l + 1) / 2; 29 } 30 31 inline ll cal2(ll n) {//這是求x + 2*x^2 + ... + n*x^n的函數 32 ll a = n % mod * ksm(x, n + 1) % mod * (x - 1) % mod; 33 ll b = x * sub(ksm(x, n), 1) % mod; 34 return sub(a, b) * ksm((x - 1) * (x - 1) % mod, mod - 2) % mod; 35 } 36 37 int main() { 38 cin >> N >> K; 39 x = N + 1; 40 if (K == 0) { 41 cout << cal2(N) << endl; 42 return 0; 43 } 44 ll l = 1, r = N; 45 while (l < r) { 46 ll mid = (l + r) >> 1; 47 if (cal(N - mid, N - 1) <= K) l = mid + 1; 48 else r = mid; 49 } 50 while (cal(N - l, N - 1) >= K) l--;//至此l為第一段長度。如果出現54312這種,會將54作為第一段,3作為第二段,12為第三段,第四段為空 51 if (l) { 52 ans1 = add(sub(x * x % mod * (ksm(x, l) - 1 + mod) % mod * ksm(x - 1, mod - 2) % mod, l * x % mod), (N - l) * x % mod * (ksm(x, l) - 1 + mod) % mod) * ksm(x - 1, mod - 2) % mod; 53 K -= cal(N - l, N - 1); 54 } 55 if (K) { 56 K++, l++;//K就是第二段那個數字,l++只是為了運算簡便 57 ans2 = K % mod * ksm(x, l) % mod; 58 ans3 = ksm(x, l) * cal2(K - 1) % mod; 59 if (N - l + 1 > K) {//如果有第四段 60 ll tmp = K % mod * sub(ksm(x, N + 1), ksm(x, K + l)) % mod * ksm(x - 1, mod - 2) % mod; 61 ans4 = add(tmp, ksm(x, K + l - 1) * cal2(N - K - l + 1) % mod); 62 } 63 } 64 cout << (ans1 + ans2 + ans3 + ans4) % mod; 65 return 0; 66 }

牛客練習賽42D(性質、數學)