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;
}
不摆烂了,写题