題意
一個四周圍都是黑色的由n行n列小格子組成的方塊,每次可以選擇一個已經由黑框包圍的正方形將它的一行一列塗黑要求分割出的部分還都是正方形,問塗k次可以有多少種不同的塗法
思路
因為只能分割成正方形,所以肯定是每一次塗最中間的行和最中間的列,那麼可以塗的次數就是不斷對n減一除以2看能做多少層,至於答案就用dp計算,從小往大,先左右變成二倍,再上下變成二倍,ans[i][j]=(ans[i][j]+(temp[k]*temp[j-1-k])%mod)%mod,ans[i][j]表示塗i層已經塗了j次的塗法數量,temp[k]表示上下一半那麼大塗k次的方法數,temp[j]=(temp[j]+(ans[i][k]*ans[i][j-k])%mod)%mod,這個就是在做左右的延展,左邊塗k次,右邊塗j-k次,一共就塗了j次,最後ans[層數][k]就是答案
代碼
#include<cstdio>#define mod 7340033long long ans[31][1001],temp[1001];int main(){ long long q,n,k,cnt; ans[0][0]=1; temp[0]=1; for(long long i=1;i<=30;i++) { ans[i][0]=1; for(long long j=1;j<=1000;j++) for(long long k=0;k<j;k++) ans[i][j]=(ans[i][j]+(temp[k]*temp[j-1-k])%mod)%mod; for(long long j=1;j<=1000;j++) temp[j]=0; temp[0]=1; for(long long j=1;j<=1000;j++) for(long long k=0;k<=j;k++) temp[j]=(temp[j]+(ans[i][k]*ans[i][j-k])%mod)%mod; } scanf("%I64d",&q); for(long long i=0;i<q;i++) { scanf("%I64d%I64d",&n,&k); cnt=0; while((n%2)&&n>1) { cnt++; n/=2; } printf("%I64d\n",ans[cnt][k]); } return 0;}