Avito Cool Challenge 2018:C. Colorful Bricks
阿新 • • 發佈:2018-12-18
C. Colorful Bricks
題目連結:https://codeforces.com/contest/1081/problem/C
題意:
有n個橫向方塊,一共有m種顏色,然後有k個方塊的顏色與其左邊的顏色不同(第一個除外),問一共有多少染色方案。
題解:
我們首先來考慮一下dp。
設dp(i,j)為當前第i個方塊,一共有j個方塊與它前面的方塊不同的方案個數。
那麼轉移方程為dp(i,j)=dp(i-1,j-1)*(m-1)+dp(i-1,j)。
程式碼如下:
#include <bits/stdc++.h> usingView Codenamespace std; typedef long long ll; const int MOD = 998244353,N = 2005; ll n,m,k; ll dp[N][N]; int main(){ cin>>n>>m>>k; dp[1][0]=m; for(int i=2;i<=n;i++){ for(int j=0;j<i;j++){ dp[i][j]=dp[i-1][j]; if(j!=0) dp[i][j]=(dp[i][j]+dp[i-1][j-1]*(m-1))%MOD; } } cout<<dp[n][k]; return 0; }
還有一種數學的計數方法。
我們假設已經選定了k種顏色,除開第一個,那麼我們就可以直接把2-n的位置進行縮點,縮成有前一個的顏色不等於後一個顏色的點(因為有一些點的顏色是和之前的點顏色相等的,這種對答案沒有貢獻,取決於之前的那個顏色)。
然後第一個位置有m種情況,之後的每個位置都有m-1種情況。
所以最後答案為C(n-1,k)*m*(m-1)^k。
程式碼如下:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MOD = 998244353 ,N = 2005; ll n,m,k; ll C[N][N]; ll qp(ll a,ll b){ ll ans = 1; while(b){ if(b&1) ans=(a*ans)%MOD; a=(a*a)%MOD; b>>=1; } return ans ; } int main(){ cin>>n>>m>>k; C[0][0]=C[1][1]=1; for(int i=1;i<=n;i++) C[i][0]=1; for(int i=2;i<=n;i++) for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD; ll ans = (C[n-1][k]*m)%MOD; cout<<ans*qp(m-1,k)%MOD<<endl; return 0; }View Code