牛客 369A 小D的劇場(線性dp)

2021-09-10 23:51:20 字數 3276 閱讀 9257

題幹:

題目描述

"我明白。"

作為這命運劇場永遠的觀眾,小d一直注視著這片星光璀璨的舞台,舞台上,少女們的身姿演繹出了一幕幕動人的場景,令人回味無窮。

有的時候,小d也會自己寫一些歌曲,來加入starlight的劇本,使得劇本充滿了新的生命力。

現在小d又要準備寫樂譜了,小d寫譜的方式比較獨特。他會先寫出乙個按照音符出現順序排成的序列,再進一步整合,每次整合會選取相鄰的三個作為三和弦。整合次數無限。

小d選取的音符形如d5 f6這種形式,例如d5表示d大調sol(這裡不考慮公升降音)為了方便生成樂譜,他將這些音符進一步轉化了,小d給c d e f g a b重新編號成了1 2 3 4 5 6 7,之後新的音符編號生成方式應為(字母對應的標號-1)*7+數字,例如c7=(1−1)×7+7=7c7=(1−1)×7+7=7

但小d討厭一些他所認為的不優美的和弦,因此他並不希望自己的譜子裡面有可能出現這樣的三和弦,也就說音符組成的序列裡不應該存在他所討厭的子段,假如c5 f1 a2這三個音符湊成的和弦小d不喜歡,那麼序列裡面就不能出現c5 f1 a2,c5 a2 f1,a2 c5 f1,a2 f1 c5,f1 a2 c5,f1 c5 a2這六種子段。

現在小d正在推算有多少合法的序列,答案對 109+7109+7 取模。

星屑飄灑的舞台上,可人綻放的愛之花,請努力讓大家星光閃耀吧!

第一行為兩個整數 n, q ,表示序列的長度和有多少和弦小d不喜歡.

接下來 q 行,每行三個整數 a, b, c ,表示小d不想出現的和弦

一行乙個整數,表示答案
示例1

複製

10 10

18 3 3

43 28 22

42 28 3

48 48 4

29 9 31

47 9 22

1 22 49

15 48 29

2 8 27

4 24 34

複製

382785822
示例2

複製

3 1

1 2 3

複製

117643
一共有6種不合法的序列:

1 2 3

1 3 2

2 1 3

2 3 1

3 1 2

3 2 1

答案為493−6=117643493−6=117643

3≤n≤500,0≤q≤117649,1≤a,b,c≤49
解題報告:

眼殘黨表示剛開始沒有讀題、、認為q<=117649 ,正好是49^3嘛,肯定不會有重複,然後就gg了、、

dp[i][j][k]表示前i個字元,其中倒數第二個為j,倒數第乙個為k時,可以組成的方案數。

對於狀態的轉移,我們有兩種解法:對於dp[i]的轉移,我們先把源自dp[i-1]的都累加過來,然後看看需要減去多少,這時候列舉去重完的這tot組和弦,對於每一組,分成:三個數都相同;其中兩個數相同,三個數都不相同,三種情況,分別進行轉移就行了。你如果都直接減6組的話,,那就有可能減多了,樣例1就過不了(別問我怎麼知道的,吃完飯回來才想出來)。

第二種解法:也是十分簡單的,先用三維陣列標記三位數是否出現過,直接列舉後三個數[j][k][l],如果沒出現過,那就轉移;如果出現過就continue。

ac**1:

#include#include#include#include#include#include#include#include#include#include#define ll long long

#define pb push_back

#define pm make_pair

using namespace std;

const int max = 2e5 + 5;

ll dp[505][55][55],***[max];

int a[max],b[max],c[max],qq[3];

const ll mod = 1e9 + 7;

int tot;

set> > ss;

int main()

for(int i = 1; i<=2; i++)

} }for(int i = 3; i<=n; i++)

}}// memset(***,0,sizeof ***);

// //求出以i中間的,***[i]

// for(int j = 1; j<=49; j++)

// }

for(int e = 1; e<=tot; e++)

else if(a!=b && b==c)

else

}} ll ans = 0;

for(int j = 1; j<=49; j++)

} printf("%lld\n",ans);

return 0 ;

}/*4 11 2 3

3 11 1 2

*/

ac**2:

#include#include#include#include#include#include#include#include#include#include#define ll long long

#define pb push_back

#define pm make_pair

using namespace std;

const int max = 2e5 + 5;

ll dp[505][55][55],***[max];

bool bk[55][55][55];

const ll mod = 1e9 + 7;

int main()

for(int i = 1; i<=2; i++)

} }for(int i = 3; i<=n; i++)

}} }

ll ans = 0;

for(int j = 1; j<=49; j++)

} printf("%lld\n",ans);

return 0 ;

}/*4 11 2 3

3 11 1 2

*/

A 小D的劇場 牛客練習賽40 dp

題目的意思就是長度為n的序列,每個位置可以選擇1 49的數字,但是連續的3個不能出現他不喜歡的三和弦所有排列,問有多少種滿足條件的序列。由於n很小使用dp求解,記錄當前位置和上一位使用了哪些數字,複雜度o 49 3 n 令d i j k 表示長度為i的序列最後一位為k倒數第二位為j的情況數量,在轉移...

小D的劇場(思維dp)

時間限制 c c 1秒,其他語言2秒 空間限制 c c 131072k,其他語言262144k 64bit io format lld 若你摘得小的星星 你將得到小的幸福 若你摘得大的星星 你將得到大的財富 若兩者都能摘得 你將得到永遠的願望 摘星是罪孽的寬恕 摘星是夜晚的奇蹟 抓住它吧 你所期望的...

牛客小白月賽13 D 小A的位運算

題目描述 位運算是乙個非常重要的東西。而小a最近在學習位運算,小a看到了一道很簡單的例題,是說從n個數裡面選出n 1個數要讓它們或起來的值最大,小a想知道這個答案是多少。你可以幫幫他嗎?輸入描述 第一行乙個整數n表示有n個數接下來一行n個數表示a1,a2 an 輸出描述 一行輸出個結果代表最大值 示...