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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[CQOI2018] 交错序列(矩阵加速优化dp)

發布時間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [CQOI2018] 交错序列(矩阵加速优化dp) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

problem

luogu-P4456

solution

預處理階乘和階乘的逆元,枚舉 111 出現次數 iii∑(n?i+1i)(n?i)aib\sum\binom{n-i+1}{i}(n-i)^ai^b(in?i+1?)(n?i)aib。

  • (n?i+1i)\binom{n-i+1}{i}(in?i+1?) 如何推出來?

    nnn 個中選 iii(ni)\binom ni(in?)。容斥不太可能。

    隔板法。分成 iii 堆需要插 i?1i-1i?1 塊板。

    考慮 111 不能連續也就是說兩塊板之間至少要隔兩個盒子。

    隔板法經典強制每個至少有 111 個的方法類比過來。

    發現只需要拿走 i?1i-1i?1 個盒子,剩下的選的位置就可以相鄰。

但這樣是不行的,快速冪部分耗時大,且 n,mn,mn,m 之間大小關系不定,逆元可能不存在,無法預處理。

考慮解決組合數計算部分。

  • lucas\text{lucas}lucas 定理算。

    不能在要求時間內通過。

  • 算一個組合數,可以將分子分母質因數分解,然后在指數位置進行加減運算。最后在把所有質因數乘起來,就可以巧妙避免計算逆元的問題。

    但本題組合數要求計算多個,時間開銷依然未能縮減。

考慮解決快速冪計算部分。

  • xa,ybx^a,y^bxa,yb 都是完全積性函數。

    f(i)=ia?f(xy)=(xy)a=f(x)f(y)=xayaf(i)=i^a\Rightarrow f(xy)=(xy)^a=f(x)f(y)=x^ay^af(i)=ia?f(xy)=(xy)a=f(x)f(y)=xaya

    所以可以 O(n)O(n)O(n) 線性篩。

    這是解決冪運算指數固定的常見方法。

這種做法是不能通過本題的,洛谷題解有一篇能過完全是數據問題。這里只是想記錄一些 trick\text{trick}trick。


考慮計算貢獻 xayb=(n?y)ayb=∑i=0a(ai)ni(?1)a?iya?iybx^ay^b=(n-y)^ay^b=\sum_{i=0}^a\binom ain^i(-1)^{a-i}y^{a-i}y^bxayb=(n?y)ayb=i=0a?(ia?)ni(?1)a?iya?iyb。

發現當枚舉 iii(ai)ni(?1)a?i\binom{a}{i}n^i(-1)^{a-i}(ia?)ni(?1)a?i 均為常數,唯一隨序列不同而變化的是 ya+b?iy^{a+b-i}ya+b?i,準確來說應該是 yyy

我們可以計算所有序列中 111 的個數的 a+b?ia+b-ia+b?i 次方之和,然后就可以計入答案。

f(i,j,k):f(i,j,k):f(i,j,k): 考慮前 iii 位,第 iii 位為 k∈[0,1]k\in[0,1]k[0,1],所有合法序列的 111 的個數的 jjj 次方之和,即 ∑yj\sum y^jyj。

  • iii000,則對前面無限制。沒有新增的 111 的個數,貢獻不變。

    f(i,j,0)=f(i?1,j,0)+f(i?1,j,1)f(i,j,0)=f(i-1,j,0)+f(i-1,j,1)f(i,j,0)=f(i?1,j,0)+f(i?1,j,1)。

  • iii111,則前一位不能為 111,只能從 000 轉移。

    此時將有 yj→(y+1)jy^j\rightarrow (y+1)^jyj(y+1)j 直接二項式展開。

    (y+1)j=∑k=0j(jk)yk1j?k(y+1)^j=\sum_{k=0}^j\binom jky^k1^{j-k}(y+1)j=k=0j?(kj?)yk1j?k

    所有序列的 yky^kyk 之和恰恰是 f(,k,)f(,k,)f(,k,) 的定義。

    所以轉移為:f(i,j,1)=∑k=0j(jk)f(i?1,k,0)f(i,j,1)=\sum_{k=0}^j\binom jkf(i-1,k,0)f(i,j,1)=k=0j?(kj?)f(i?1,k,0)

發現轉移壓根和 iii 這一維沒有關系,所以是可以矩陣加速 nnn 的。

注意我們要計算到 ya+by^{a+b}ya+b 次方,且我們將兩種轉移合并在一起。

構造初始矩陣 f:[f0,0,f1,0,...,fa+b,0,f0,1,f1,1,...,fa+b,1]f:[f_{0,0},f_{1,0},...,f_{a+b,0},f_{0,1},f_{1,1},...,f_{a+b,1}]f:[f0,0?,f1,0?,...,fa+b,0?,f0,1?,f1,1?,...,fa+b,1?]。形式化為 [fj,0∣fj,1],j∈[0,a+b][f_{j,0}\mid f_{j,1}],j\in[0,a+b][fj,0?fj,1?],j[0,a+b]。

構造加速矩陣 ggg:分拆為四個部分。

  • 左上角為單位矩陣。表示 f(,0)→f′(,0)f(,0)\rightarrow f'(,0)f(,0)f(,0)。
  • 左下角為單位矩陣。表示 f(,1)→f′(,0)f(,1)\rightarrow f'(,0)f(,1)f(,0)
  • 右上角為組合數矩陣。注意是行列交換了的,表示 f(,0)→f′(,1)f(,0)\rightarrow f'(,1)f(,0)f(,1)。
  • 右下角為全 000 矩陣。表示不合法 f(,1)→f′(,1)f(,1)\rightarrow f'(,1)f(,1)f(,1)。

具體可以自己畫一下,發現是匹配的。

code

#include <bits/stdc++.h> using namespace std; #define int long long #define maxn 185 int n, a, b, mod, m1, m2; int C[maxn][maxn]; struct matrix {int c[maxn][maxn];matrix() { memset( c, 0, sizeof( c ) ); }matrix operator * ( matrix &v ) {matrix ans;for( int i = 0;i < m2;i ++ )for( int k = 0;k < m2;k ++ )if( c[i][k] ) //稀疏矩陣經典有效優化for( int j = 0;j < m2;j ++ ) //j,k交換 內存訪問連續 優化常數ans.c[i][j] = (ans.c[i][j] + c[i][k] * v.c[k][j]) % mod;return ans;} }g, f;signed main() {scanf( "%lld %lld %lld %lld", &n, &a, &b, &mod );m1 = a + b + 1, m2 = m1 << 1;for( int i = 0;i <= m1;i ++ ) {C[i][0] = C[i][i] = 1;for( int j = 1;j < i;j ++ )C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;}for( int i = 0;i < m1;i ++ ) {g.c[i][i] = g.c[i + m1][i] = 1;for( int j = i;j < m1;j ++ )g.c[i][j + m1] = C[j][i];}f.c[0][0] = 1; int x = n;while( x ) {if( x & 1 ) f = f * g;g = g * g;x >>= 1;}x = 1; int ans = 0;for( int i = 0;i <= a;i ++, x = x * n % mod )if( (a - i) & 1 )(ans -= (f.c[0][a+b-i] + f.c[0][a+b-i+m1]) % mod * C[a][i] % mod * x) %= mod;else (ans += (f.c[0][a+b-i] + f.c[0][a+b-i+m1]) % mod * C[a][i] % mod * x) %= mod;printf( "%lld\n", (ans + mod) % mod );return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的[CQOI2018] 交错序列(矩阵加速优化dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

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