牛客练习赛40A题

题目链接:https://ac.nowcoder.com/acm/contest/369/A

题目描述

作为这命运剧场永远的观众,小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=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+7 取模。星屑飘洒的舞台上,可人绽放的爱之花,请努力让大家星光闪耀吧!

输入描述

第一行为两个整数 n, q ,表示序列的长度和有多少和弦小D不喜欢.接下来 q 行,每行三个整数 a, b, c ,表示小D不想出现的和弦

输出描述
一行一个整数,表示答案

输入样例
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

输入样例
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=117643

数据范围
3≤n≤500,0≤q≤117649,1≤a,b,c≤49

思路:dp[i][j][k]表示第i位为k,i-1位为j时的方案数,dp[i][k][l]=dp[i][k][l]+vis[j][k][l]*dp[i-1][j][k],vis[j][k][l]=1表示合法。每一步都要取余。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include
#include
#include
#include
using namespace std;
typedef long long ll;
template <class T>
inline void read(T &n) {
T ans = 0;
char ch = '+';
int flag = 0;
while (ch<'0' || ch>'9') {
ch = getchar();
if (ch == '-')
flag = 1;
}
while (ch >= '0'&&ch <= '9') {
ans = ans * 10 + ch - 48;
ch = getchar();
}
n = flag == 1 ? -ans : ans;
}
ll dp[550][50][50];
int vis[50][50][50];
const ll maxn = 1e9 + 7;
int main() {
int n, m;
read(n), read(m);
memset(dp, 0,sizeof(dp));
int x, y, z;
for (int i = 0; i <= 50; i++) {
for (int j = 0; j <= 50; j++) {
for (int k = 0; k <= 50; k++) {
vis[i][j][k] = 1;
}
}
}
for (register int i = 1; i <= m; ++i) {
read(x), read(y), read(z);
vis[x][y][z] = vis[x][z][y] = 0;
vis[y][x][z] = vis[y][z][x] = 0;
vis[z][x][y] = vis[z][y][x] = 0;
}
dp[0][0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 50; j++) {
for (int k = 0; k < 50; k++) {
for (int l=1; l < 50; l++) {
dp[i][k][l] = (dp[i][k][l] + vis[j][k][l] * dp[i - 1][j][k]) % maxn;
}
}
}
}
ll ans = 0;
for (int i = 0; i < 50; i++) {
for (int j = 0; j < 50; j++) {
ans = (ans + dp[n][i][j]) % maxn;
}
}
printf("%lld\n", ans);
system("pause");
}

谢谢你请我吃糖果

你可能感兴趣的:(牛客练习赛40A题)