zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
    
    不摆烂了,写题
  • 相关阅读:
    归并排序
    希尔排序和插入排序的关系
    相对路径与绝对路径
    httpservlet类中两个service方法
    假如生活欺骗了你
    循环队列判满和判空的两种方式
    并查集,带权,水题PKOJ1703
    字典树HDU1251
    POJ食物链,并查集,包含种类的分部
    HDU1043逆向bfs打表
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15386768.html
Copyright © 2011-2022 走看看