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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

AtCoder 4169 [ARC100D] Colorful Sequences(dp)

發(fā)布時間:2023/12/3 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AtCoder 4169 [ARC100D] Colorful Sequences(dp) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

problem

洛谷鏈接

solution

逆向考慮。ans=ans=ans= 所有蛋糕中的 aaa 序列出現(xiàn)次數(shù) ?-?non?colorfulnon-colorfulnon?colorful 蛋糕中的出現(xiàn)次數(shù)。

在所有蛋糕中的出現(xiàn)次數(shù),即 (n?m+1)?kn?m(n-m+1)·k^{n-m}(n?m+1)?kn?m,枚舉 aaa 序列開頭的位置,除去 aaa 序列占據(jù)的位置以外的位置的顏色是隨便的 1~k1\sim k1k

因為 aaa 的出現(xiàn)是可以有重復位置的,所以每個位置的序列的貢獻都是獨立計算的,沒有什么需要去重的問題。

然后考慮在 non?colorfulnon-colorfulnon?colorful 蛋糕中的出現(xiàn)次數(shù)。

  • 首先得特判,aaa 本身就已經(jīng)是一個 colorfulcolorfulcolorful 蛋糕。那么只要包含 aaa 就一定是滿足條件的蛋糕。

    直接輸出在所有蛋糕中的出現(xiàn)次數(shù)結束程序。

  • aaa 蛋糕顏色序列中各個顏色互不相同。

    考慮用 dpdpdp 來做。

    f(i,j):f(i,j):f(i,j):iii 為止,后面一段連續(xù)顏色各不相同的長度為 jjj,即 [i?j+1,i][i-j+1,i][i?j+1,i] 顏色互不相同,的 non?colorfulnon-colorfulnon?colorful 蛋糕個數(shù)。

    設計 i?1→ii-1\rightarrow ii?1i 的轉移方程。

    • 隨便新選一個未曾出現(xiàn)的顏色。

      f(i?1,j?1)?(k?j+1)→f(i,j):f(i-1,j-1)·(k-j+1)\rightarrow f(i,j):f(i?1,j?1)?(k?j+1)f(i,j):

    • i?1i-1i?1 的長度更長,在 iii 時選擇了和恰當位置相同顏色,將 i?1i-1i?1 恰好卡成了 jjj 的長度。

      f(i?1,j′)→f(i,j)j′≥jf(i-1,j')\rightarrow f(i,j)\quad j'\ge jf(i?1,j)f(i,j)jj

    gi,j:g_{i,j}:gi,j?: 記錄 fi,jf_{i,j}fi,j? 類的所有可能蛋糕中出現(xiàn) a1,...,ma_{1,...,m}a1,...,m? 的個數(shù)。

    事實上,我們轉移時并不知道具體的蛋糕長相,所以不能判斷是否連續(xù)長度為 mmm 的未重復的就一定是 aaa

    所以在轉移時只要 j≥mj\ge mjm,即出現(xiàn)連續(xù)長度達到 mmm 的互不相同顏色的連續(xù)蛋糕層,就記錄貢獻。

    f(i,j)→g(i,j)f(i,j)\rightarrow g(i,j)f(i,j)g(i,j)

    因為連續(xù)長度有 mmm 的連續(xù)蛋糕層的每種情況都是均勻分布,最后限制其順序和顏色值,即 /A(k,m)/A(k,m)/A(k,m) 即可。

  • aaa 蛋糕顏色序列中有重復顏色。

    也就是說,判斷一個蛋糕是否是 colorfulcolorfulcolorful 的區(qū)間一定不會橫跨 / 完全包含 aaa

    那么 aaa 就將整個蛋糕劃分成了前一部分,aaa ,后一部分,三部分彼此獨立。

    枚舉 aaa 的開始位置,可以使用卷積 / 乘法定理求左右蛋糕組合情況,分開求解,進而是一整個蛋糕的顏色序列可能數(shù)。

    顯然,求解計算的 non?colorfulnon-colorfulnon?colorful 個數(shù)與上面 fff 是一樣的轉移。

    只是在初始化上有所不同。

    aaa 求前綴和后綴最長不重復顏色長度,分別記為 l,rl,rl,r

    f(i,j)f(i,j)f(i,j) 來計算前一部分,g(i,j)g(i,j)g(i,j) 來計算后一部分,這里的 f,gf,gf,g 與上一種情況的 f,gf,gf,g 并不一樣。

    f0,0=f0,1=...=f0,l=g0,0=g0,1=...=g0,r=1f_{0,0}=f_{0,1}=...=f_{0,l}=g_{0,0}=g_{0,1}=...=g_{0,r}=1f0,0?=f0,1?=...=f0,l?=g0,0?=g0,1?=...=g0,r?=1

  • 注意:這里算的是 non?colorfulnon-colorfulnon?colorful 蛋糕中的貢獻,所以在 dpdpdp 中不能讓連續(xù)未重復顏色長度達到 kkk

code

#include <bits/stdc++.h> using namespace std; #define mod 1000000007 #define int long long #define maxn 25005 #define maxk 405 int n, k, m; int a[maxn]; int f[maxn][maxk], g[maxn][maxk]; bool vis[maxk];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans; }bool check( int l, int r ) {memset( vis, 0, sizeof( vis ) );for( int i = l;i <= r;i ++ )if( vis[a[i]] ) return 0;else vis[a[i]] = 1;return 1; }bool colorful() { //判斷a是否本身就是彩虹的for( int i = 1;i + k - 1 <= m;i ++ )if( check( i, i + k - 1 ) ) return 1;return 0; }signed main() {scanf( "%lld %lld %lld", &n, &k, &m );for( int i = 1;i <= m;i ++ ) scanf( "%lld", &a[i] );int ans = ( n - m + 1 ) * qkpow( k, n - m ) % mod;if( colorful() ) return ! printf( "%lld\n", ans );int l = -1, r = -1;memset( vis, 0, sizeof( vis ) );for( int i = 1;i <= m;i ++ )if( vis[a[i]] ) { l = i - 1; break; }else vis[a[i]] = 1;memset( vis, 0, sizeof( vis ) );for( int i = m;i >= 1;i -- )if( vis[a[i]] ) { r = m - i; break; }else vis[a[i]] = 1;int tot;if( ! ~l ) {f[0][0] = 1;for( int i = 1;i <= n;i ++ ) {for( int j = 1;j < k;j ++ ) {/*因為不能是colorful所以不能讓未重復長度達到k1.f[i-1][j-1]->f[i][j] 隨便加一個未出現(xiàn)的數(shù)字 有(k-j+1)種因為f'[i-1]是后綴和過的 f'[i-1][j-1]-f'[i-1][j]=f[i-1][j-1]2.f[i-1][j<=j']->f[i][j] 選擇合適位置對應的數(shù)字 將未重復長度減小因為f'[i-1]是后綴和過的 f[i-1][j<=j']=f[i][j]*/f[i][j] = ((f[i - 1][j - 1] - f[i - 1][j] + mod) % mod * (k - j + 1) % mod + f[i - 1][j]) % mod;g[i][j] = ((g[i - 1][j - 1] - g[i - 1][j] + mod) % mod * (k - j + 1) % mod + g[i - 1][j]) % mod;if( j >= m ) ( g[i][j] += f[i][j] ) %= mod; //當長度達到m的時候就可以計算個數(shù)了}for( int j = k - 1;j;j -- ) { //后綴和( f[i][j - 1] += f[i][j] ) %= mod;( g[i][j - 1] += g[i][j] ) %= mod;}}tot = g[n][0]; //此時的g只是算的長度為m的未重復的個數(shù) 包含了給出的a 還有一些其余的數(shù)列//這里的a強調(diào)順序以及數(shù)值 所以要除以A(k,m)for( int i = k;i > k - m;i -- ) tot = tot * qkpow( i, mod - 2 ) % mod;}else {//前后卷積for( int i = 0;i <= l;i ++ ) f[0][i] = 1;for( int i = 0;i <= r;i ++ ) g[0][i] = 1;for( int i = 1;i <= n;i ++ ) {for( int j = 1;j < k;j ++ ) {f[i][j] = ((f[i - 1][j - 1] - f[i - 1][j] + mod) % mod * (k - j + 1) % mod + f[i - 1][j]) % mod;g[i][j] = ((g[i - 1][j - 1] - g[i - 1][j] + mod) % mod * (k - j + 1) % mod + g[i - 1][j]) % mod;}for( int j = k - 1;j;j -- ) {( f[i][j - 1] += f[i][j] ) %= mod;( g[i][j - 1] += g[i][j] ) %= mod;}}tot = 0;for( int i = 0;i <= n - m;i ++ )tot = ( tot + f[i][0] * g[n - m - i][0] % mod ) % mod;}printf( "%lld\n", ( ans - tot + mod ) % mod );return 0; }

總結

以上是生活随笔為你收集整理的AtCoder 4169 [ARC100D] Colorful Sequences(dp)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。