/*題意:杭州邀請賽的一道題;有標記著1~n的環,初始時有個機器人在1的位置,有m個操作,每個操作是使機器人隨機的順時針或逆時針的走w步,求所有操作過後機器人停在區間[l,r]內的機率;思路:挺明顯的機率dp,首先可以很直觀的定義出狀態dp[i][j],表示第j次操作後停留在第i位置的機率,轉移方程是 dp[(i + w) % n][j] = dp[i[j-1] * 0.5;dp[i-w][j]=dp[i][j-1]*0.5;其中i-w不斷的加n使它大於等於0;但是題目運算元比較大,這樣會超記憶體,觀察發現每次轉移只和上一次操作有關,所以可以用個滾動數組來節省空間的;最佳化空間後轉移方程是 dp[(i + w) % n][j&1] += dp[i][!(j&1)] * 0.5;dp[x][j&1] += dp[i][!(j&1)] * 0.5;x=i-w,x也要疊加到非負;最後答案就是所有操作完後,位置l到r的機率總和。*/#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;#define manx 209double dp[manx][2];const double eps=0.0;int main(){ int n,m,l,r; while(cin>>n>>m>>l>>r){ if(n==0 && m==0 && l==0 && r==0) break; int w,i,j; for(i=0;i<n;i++) dp[i][0]=dp[i][1]=0; dp[0][0] = 1.0; for(j=1;j<=m;j++){ scanf("%d",&w); for(i=0;i<n;i++){ dp[(i+w)%n][j&1] += dp[i][!(j&1)]*0.5; int ans = i - w; if(ans<0) ans += n; dp[ans][j&1] += dp[i][!(j&1)]*0.5; } for(i=0;i<=n;i++) dp[i][!(j&1)] = eps; } double res = 0.0; l--,r--; for(i=0;i<n;i++) if(i>=l && i<=r) res += dp[i][m&1]; printf("%.4lf\n",res); }}