題意:要求長度為N的位元字中,它的所有字串(注意是any)中0 1的差的絕對值不大於K。
做法:從長度為1 的時候開始算起,每一次操作都是增加了一個1或者一個0,那麼可以為用這個當做狀態,記得狀態劃分時,增加末尾數字改變的是任何一個含有末尾字元的字串中0,1的數量,這裡就有一個遞推關係了,要目前狀態的尾碼字串有效,那麼必須它的前面的那個字元夠成的尾碼字串有效,這樣一來,最終會把所有字串中的所有字串考慮進去。一開始是想考慮所有首碼串的,可是無法與狀態結合起來啊。。。。
#include <iostream>#include <cstdio>#include <cstring>#define LMT 65#define LL long longusing namespace std;LL dp[LMT][135][135],ans;int k,n;void init(void){ memset(dp,0,sizeof(dp)); ans=0;}inline int abs(int x){ return x>0?x:-x;}int main(){ while(~scanf("%d%d",&n,&k)) { init(); dp[1][LMT+1][LMT-1]=dp[1][LMT-1][LMT+1]=1; for(int i=1;i<n;i++) for(int j=-i+LMT;j<=i+LMT;j++) for(int t=-i+LMT;t<=i+LMT;t++) { int k1=j-LMT,k2=t-LMT,num; if(abs(k1+1)<=k&&abs(k2-1)<=k) { num=(k1>=0?k1:0)+1; dp[i+1][num+LMT][k2-1+LMT]+=dp[i][j][t]; } if(abs(k1-1)<=k&&abs(k2+1)<=k) { num=(k2>=0?k2:0)+1; dp[i+1][k1-1+LMT][num+LMT]+=dp[i][j][t]; } } for(int j=-n+LMT;j<=n+LMT;j++) for(int t=-n+LMT;t<=n+LMT;t++) ans+=dp[n][j][t]; printf("%lld\n",ans); } return 0;}