1. 程式人生 > >牛客練習賽40 A 小D的劇場 (思維dp)

牛客練習賽40 A 小D的劇場 (思維dp)

思路 while ram names 方案 音符 contest -i describe

鏈接:https://ac.nowcoder.com/acm/contest/369/A

題目描述

若你摘得小的星星 你將得到小的幸福 若你摘得大的星星 你將得到大的財富 若兩者都能摘得 你將得到永遠的願望 摘星是罪孽的寬恕 摘星是夜晚的奇跡 抓住它吧 你所期望的那顆星
無法觸及,因而耀眼 明明觸及了,卻還是耀眼

——《少女☆歌劇 Revue·Starlight》

題目描述

"我明白。" 作為這命運劇場永遠的觀眾,小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=(11)×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


題意:給你一個序列長度n,現在每一個位置都有49種方案可以填入,再給出q種不合法的方案 問有多少種可行方案
結果對1e9+7取模
思路: dp[i][k][l] 表示第i各位置放置 k和l兩種音符 我們只需要枚舉49^3種情況 對於 j k l 可行的情況 我們就有遞推式
dp[i][k][l]+=dp[i-1][j][k]
其實這麽看來問題就沒那麽復雜了
#include <cstdio>
#include <map>
#include <iostream>
#include<cstring>
#include<bits/stdc++.h>
#define ll long long int
#define M 6
using namespace std;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1};
int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1};
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
int n,q;
ll dp[507][57][57];  //dp[i][k][l] 表示第i各位置放置 k和l兩種音符 
int a[50][50][50];
int main(){
    ios::sync_with_stdio(false);
    while(cin>>n>>q){
        memset(a,0,sizeof(a));
        for(int i=1;i<=q;i++){
            int ta,tb,tc;
            cin>>ta>>tb>>tc;
            a[ta][tb][tc]=1; a[ta][tc][tb]=1;
            a[tb][ta][tc]=1; a[tb][tc][ta]=1;    //對不可行方案進行標記 
            a[tc][ta][tb]=1; a[tc][tb][ta]=1;
        }
        for(int i=1;i<=2;i++)
            for(int j=1;j<=49;j++)
                for(int k=1;k<=49;k++)        //初始化 
                    dp[i][j][k]=1;
                    
        for(int i=3;i<=n;i++)
            for(int j=1;j<=49;j++)
                for(int k=1;k<=49;k++)
                    for(int l=1;l<=49;l++){
                        if(a[j][k][l]) continue;    
                        dp[i][k][l]=(dp[i][k][l]+dp[i-1][j][k])%mod;    
                        //如果是可行方案則 jk的後面就可以是l 
                    }
        ll ans=0;
        for(int i=1;i<=49;i++)
            for(int j=1;j<=49;j++){
                ans=(ans+dp[n][i][j])%mod;
            }
        cout<<ans<<endl;
    }
}

牛客練習賽40 A 小D的劇場 (思維dp)