題目的意思就是長度為n的序列,每個位置可以選擇1~49的數字,但是連續的3個不能出現他不喜歡的三和弦所有排列,問有多少種滿足條件的序列。
由於n很小使用dp求解,記錄當前位置和上一位使用了哪些數字,複雜度o(49^3*n)
令d[i][j][k]表示長度為i的序列最後一位為k倒數第二位為j的情況數量,在轉移時遍歷當前位和前兩位所用數值進行轉移。
轉移方程d[l][j][k] = d[l][j][k] + d[l - 1][i][j],l表示長度ijk為後三位,轉移時候注意判斷ijk所組成的三和弦是否滿足條件。
#include
#include
#define fst first
#define sed second
using namespace std;
typedef
long
long ll;
const
int inf =
0x3f3f3f3f
;const ll linf =
0x3f3f3f3f3f3f3f3f
;const
int mod =
1e9+7;
const
int maxn =
5e2+10;
const
int maxm =50;
ll d[maxn]
[maxm]
[maxm]
;//d[i][j][k]表示長度為i當前位用k上一位用j的方案數量
bool x[maxm]
[maxm]
[maxm]
;//非法狀態
intmain()
d[0][
0][0
]=1;
for(
int l =
1; l <= n; l++
)for
(int i =
0; i <
50; i++
)//列舉連續三位
for(
int j =
0; j <
50; j++
)for
(int k =
1; k <
50; k++
)//新的位置只能從1開始if(
!x[i]
[j][k]
)//不是非法狀態
d[l]
[j][k]
=(d[l]
[j][k]
+ d[l -1]
[i][j]
)% mod;
ll ans =0;
for(
int j =
1; j <
50; j++
)for
(int k =
1; k <
50; k++
) ans =
(ans + d[n]
[j][k]
)% mod;
cout << ans << endl;
return0;
}
牛客練習賽40
題目鏈結 c題 小a與尤拉路 先考慮迴路的情況。由於是一棵樹,任兩點間路徑只有一條,從一條邊走到深度更大的點,一定還會從同一條邊返回以回到起點或者遍歷其他子樹,所以每條邊需要複製一次,此時答案是邊權和的兩倍。不是迴路的情況可以減掉從終點回到起點的路徑,要讓這條路徑盡量長,所以長度一定是直徑的長度。答...
牛客練習賽58 D 迷宮 dp
考慮到無論往左走還是往下走,下一步又會回來,進而不斷在兩個格仔間來回跳,所以只能往右走或者往下走,並且優先往右走 設 f i j 表示走到 i,j 的最小操作次數,考慮轉移 begin f i j to f i j 1 f i j s i j 1 0 to f i 1 j end 暴力轉移即可 我個...
牛客練習賽40 題解(部分)
官方題解 a 小d的劇場 大概意思就是,有1 49個數,代表著不同的音符,問你能組成長度為n的串有多少種 mod 109 7 有若干個限制,比如1 2 3,就是1,2,3不能放在一起,然後問你在這些限制下有多少種不同的長度為n的串。3 n 500,0 q 117649,1 a,b,c 49 思路 看...