【LOJ#10172】涂抹果酱
尽管本题依旧是状压dp,但是不同的是本题的状态无法用二进制表示,而需要三进制。三进制特殊的地方在于位运算符全都不能用了,因此本题比往常的题目多了一部分,就是手写判断,而不是直接&,|,^.
可喜的是,本题状态定义极其简单,定义f[i][j]表示第i行的状态为j时,前i行的方案数,这样一来,本题与“国王”“牧场的安排”很类似,在此不再赘述。
1 #include <bits/stdc++.h> 2 #define ll long long 3 #define mod 1000000 4 #define N 10005 5 using namespace std; 6 int n,m,K,ban,ans=0,sta[1005],tot=0,stat,f[N][1005],bit[6],pos; 7 inline bool check(int x) { 8 int tmp=0x3f; 9 for(int i=1; i<=m; ++i) { 10 if(tmp==x%3)return false; 11 tmp=x%3,x/=3; 12 } 13 return true; 14 } 15 inline int read() { 16 int ans=0; 17 char ch=getchar(); 18 while(!isdigit(ch))ch=getchar(); 19 while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar(); 20 return ans; 21 } 22 inline bool judge(int a,int b) { 23 for(int i=1; i<=m; ++i) { 24 if(a%3==b%3)return false; 25 a/=3,b/=3; 26 } 27 return true; 28 } 29 int main() { 30 n=read(),m=read(),K=read(),stat=1; 31 for(int i=1; i<=m; ++i)stat*=3; 32 for(int i=0; i<stat; ++i)if(check(i))sta[++tot]=i; 33 for(int i=1; i<=m; ++i)ban=ban*3+read()-1; 34 for(int i=1; i<=tot; ++i)if(ban==sta[i]) { 35 pos=i; 36 break; 37 } 38 if(!pos) { 39 puts("0"); 40 return 0; 41 } 42 for(int i=1; i<=n; ++i) { 43 if(i==K) { 44 if(i==1)f[i][pos]=1; 45 else for(int j=1; j<=tot; ++j)if(judge(sta[pos],sta[j])) 46 (f[i][pos]+=f[i-1][j])%=mod; 47 } 48 else 49 for(int j=1; j<=tot; ++j) { 50 if(i==1) f[i][j]=1; 51 else for(int k=1; k<=tot; ++k) 52 if(judge(sta[j],sta[k])) 53 (f[i][j]+=f[i-1][k])%=mod; 54 } 55 } 56 for(int i=1;i<=tot;++i)(ans+=f[n][i])%=mod; 57 cout<<ans; 58 return 0; 59 }