E2. Rubik's Cube Coloring (hard version) 題解(dp+思維)


題目鏈接

題目思路

大佬的一句話 只考慮欽定的點連成樹然后dp

其實就是每個點和根節點連邊,那么只考慮那條鏈上的所有節點

最多\(n*k\)個點

\(dp[i][node]\)表示\(node\)節點顏色為\(i\)的方案數

注意\(num[i]\)數組不要提前取模,對於\(a^b\)的形勢一定要小心取模,找了一年bug

代碼

#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e6+5,inf=(1ll<<31)-1,mod=1e9+7;
const double eps=1e-6;
int k,n;
char s[20];
map<ll,ll> col,sz,dp[10];
ll num[70];
ll qpow(ll a,ll b){
    ll ans=1,base=a;
    while(b){
        if(b&1) ans=ans*base%mod;
        base=base*base%mod;
        b=b>>1;
    }
    return ans;
}
void dfs(ll node,int dep){
    if(sz[node]==0){
        // dep+1到k層
        for(int i=1;i<=6;i++){
            if(k==dep){
                dp[i][node]=1;
            }else{
                dp[i][node]=qpow(4,num[k-dep]);
            }
        }
        return ;
    }
    if(dep==k){
        for(int i=1;i<=6;i++){
            if(col[node]==0||i==col[node]){
                dp[i][node]=1;
            }else{
                dp[i][node]=0;
            }
        }
        return ;
    }
    dfs(node<<1,dep+1);
    dfs(node<<1|1,dep+1);
    for(int i=1;i<=6;i++){
        ll sum0=0,sum1=0;
        for(int j=1;j<=6;j++){
            if(i%2==1){
                if(j!=i&&j!=i+1){
                    sum0+=dp[j][node<<1];
                    sum1+=dp[j][node<<1|1];
                }
            }else{
                if(j!=i&&j!=i-1){
                    sum0+=dp[j][node<<1];
                    sum1+=dp[j][node<<1|1];
                }
            }
        }
        sum0%=mod,sum1%=mod;
        // 沒有強制給他顏色,或者強制給的顏色就是i顏色
        if(col[node]==0||col[node]==i){
            dp[i][node]=sum0*sum1%mod;
        }
    }
}
signed main(){
    // 不要提起對num[i]取模 因為a^b!=a^(b%mod)
    for(ll i=1;i<=60;i++){
        num[i]=(num[i-1]+(1ll<<i));
    }
    scanf("%d%d",&k,&n);
    for(int i=1;i<=n;i++){
        ll x;
        scanf("%lld %s",&x,s+1);
        if(s[1]=='w') col[x]=1;
        if(s[1]=='y') col[x]=2;
        if(s[1]=='g') col[x]=3;
        if(s[1]=='b') col[x]=4;
        if(s[1]=='r') col[x]=5;
        if(s[1]=='o') col[x]=6;
        while(x){// 標記路徑
            sz[x]=1;
            x=x/2;
        }
    }
    dfs(1,1);
    ll pr=0;
    for(int i=1;i<=6;i++){
        pr=(pr+dp[i][1])%mod;
    }
    printf("%lld\n",pr);
    return 0;
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM