1. 程式人生 > >#10172. 「一本通 5.4 練習 1」塗抹果醬 題解

#10172. 「一本通 5.4 練習 1」塗抹果醬 題解

tst num gist 輸出 def head printf admin line

題目鏈接

一道三進制狀壓的好題。

題目描述:

Tyvj 兩周年慶典要到了,Sam 想為 Tyvj 做一個大蛋糕。蛋糕俯視圖是一個 N×M的矩形,它被劃分成 
N×M個邊長為 1×1的小正方形區域(可以把蛋糕當成 N 行 M 列的矩陣)。
蛋糕很快做好了,但光禿禿的蛋糕肯定不好看!
所以,Sam 要在蛋糕的上表面塗抹果醬。果醬有三種,分別是紅果醬、綠果醬、藍果醬,
三種果醬的編號分別為
1,2,3.為了保證蛋糕的視覺效果,Admin 下達了死命令:
相鄰的區域嚴禁使用同種果醬。但 Sam 在接到這條命令之前,
已經塗好了蛋糕第 KKK 行的果醬,且無法修改。 現在 Sam 想知道:能令 Admin 滿意的塗果醬方案有多少種。請輸出方案數 mod
1e6。若不存在滿足條件的方案,請輸出 0

輸入格式

輸入共三行。
第一行:N,M
第二行:K
第三行:M 個整數,表示第 K 行的方案。
字母的詳細含義見題目描述,其他參見樣例。

輸出格式

輸出僅一行,為可行的方案總數。

樣例

樣例輸入

2 2 
1 
2 3

樣例輸出

 3 

解題思路:

這道題關鍵在判斷合法情況,第k行特判一下即可。

1.判斷一個三進制數是否有相同數字相鄰的情況,不能模擬二進制左移右移的情況,

因為這裏有3個數字,左移右移會出現有0的影響。

2.判斷不同行是否有相同數字相鄰,模擬二進制的&判斷一下即可。

代碼:

#include<bits/stdc++.h>
#define ll long long 
#define R register
using namespace std;
int  n,m,k,mod=1e6,a[250],sk,num,top,ans,f[10005][250];
inline int ksm(R int x,R int p)
{
    R int tot=1;
    while(p)
    {
        if(p&1)
        {
        tot
=tot*x; } x=x*x; p>>=1; } return tot; } inline int check(R int x,R int y) { for(R int i=1;i<=m;++i){ if((x%3)==(y%3))return 0; x/=3; y/=3; } return 1; } inline int judge(R int x) { R int y=-1; for(R int i=1;i<=m;++i) { if(y==x%3)return 0; y=x%3; x/=3; } return 1; } inline void init() { for(R int i=0;i<=242;++i){ R int x=i,tot=0; while(x) { x/=3; ++tot; } if(tot>=m+1)break; if(judge(i)){ a[++num]=i; if(i==sk)top=num; } } } int main(){ scanf("%d%d",&n,&m); scanf("%d",&k); for(R int i=1;i<=m;++i) { R int t; scanf("%d",&t); sk+=(t-1)*ksm(3,i-1); } if(!judge(sk)) { printf("0"); return 0; } init(); if(k==1) f[1][top]=1; else for(R int i=1;i<=num;++i) f[1][i]=1; for(R int i=2;i<=n;++i)//當前第幾行 { if(i==k) { for(R int t=1;t<=num;++t) if(check(a[top],a[t])) f[i][top]=(f[i][top]+f[i-1][t])%mod; } else { for(R int j=1;j<=num;++j)//當前行狀態 { if(i-1==k) { if(check(a[j],a[top])) f[i][j]=(f[i][j]+f[i-1][top])%mod; } else { for(R int t=1;t<=num;++t)//上一行狀態 if(check(a[j],a[t])) f[i][j]=(f[i][j]+f[i-1][t])%mod; } } } } for(R int i=1;i<=num;++i) ans=(ans+f[n][i])%mod; printf("%d",ans%mod); return 0; }

這道題關鍵在於舍棄不合法情況的判斷.

#10172. 「一本通 5.4 練習 1」塗抹果醬 題解