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
",pr);
    return 0;
}


不摆烂了,写题
原文地址:https://www.cnblogs.com/hunxuewangzi/p/15386768.html