第N个骑士活到最后的情况就是他在往左走的过程中一路打败迎面走来的往右走的骑士. 考虑用f(i, j)表示前i个骑士有j个往右边走的概率,分两种情况:
1) 第i个骑士初始是往左边走,于是
f(i,j)=∑k=ji−1f(i−1,k)∗(12)k−j+1f(i,j) = \sum_{k=j}^{i-1}f(i-1,k)*(\frac{1}{2})^{k-j+1}f(i,j)=∑k=ji−1f(i−1,k)∗(21)k−j+1
这是因为前i-1个人中有k个往右走,此时要使前i个人中有j个往右走,第i个人必须要赢下k-j场,再输掉一场. 由上式可得
f(i,j)=f(i,j+1)+f(i−1,j)2f(i,j) = \frac{f(i,j+1)+f(i-1,j)}{2}f(i,j)=2f(i,j+1)+f(i−1,j)
2) 第i个骑士初始是往右边走,于是f(i, j) = f(i-1, j-1). 这是因为在前面基础上加多一个往右走的.
最终结果为∑j=1n−1f(n−1,j)∗12j\sum_{j=1}^{n-1} f(n-1,j)*\frac{1}{2}^j∑j=1n−1f(n−1,j)∗21j. 复杂度O(N^2).
看了半天也没看懂是怎么转移的
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 1100010
#define MOD 1000000007
int n,m;
int a[1010];
long long dp[1010][1010],dp1[1010][1010];
long long X,Y;
long long mi(long long x,long long a,int p)
{
long long ans = 1;
x = x % p;
while(a)
{
if(a&1)
ans = (ans * x) % p;
x = (x * x) % p;
a >>= 1;
}
return ans;
}
long long gcd(long long a,long long b)
{
int t,d;
if(b == 0)
{
X = 1;
Y = 0;
return a;
}
d = gcd(b,a%b);
t = X;
X = Y;
Y = t - (a / b) * Y;
return d;
}
int main()
{
int t,C = 1;
scanf("%d",&t);
gcd(2,MOD);
X += MOD;
while(t--)
{
scanf("%d",&n);
memset(dp,0,sizeof(dp));
memset(dp1,0,sizeof(dp1));
for(int i = 1; i <= n; i++)
scanf("%d",&a[i]);
dp[1][1] = 1;
dp1[1][1] = 1;
for(int i = 2; i < n; i++)
{
// if(a[i] == 1)
// dp[i][j+1] = dp[i-1][j];
// else
// dp[i][j+1] = (dp[i][j]*2 - dp[i-1][j] + MOD)%MOD;
if(a[i] == 1)
{
for(int j = 1; j <= i; j++)
{
dp[i][j] = dp[i-1][j-1];
dp1[i][j] = dp1[i-1][j-1];
}
}
else
{
for(int j = i-1; j >= 1; j--)
{
dp[i][j] = dp[i-1][j];
}
for(int j = i-1; j >= 2; j--)
{
dp[i][j-1] = (dp[i][j-1] + dp[i][j]*X%MOD)%MOD;
dp[i][j] = dp[i][j] * X % MOD;
}
for(int j = i-1; j >= 2; j--)
{
dp1[i][j] = dp1[i-1][j]*X%MOD;
}
//for(int j = 1; j < i; j++)
//printf("%d %d %lld %lld\n",i,j,dp[i][j],dp1[i][j]);
}
}
long long ans = 0,ans1 = 0;
for(int i = 1; i < n; i++)
{
for(int j = 0; j < i; j++)
{
dp[n-1][i] = dp[n-1][i] * X % MOD;
dp1[n-1][i] = dp1[n-1][i] * X % MOD;
}
ans += dp[n-1][i];
ans %= MOD;
ans1 += dp1[n-1][i];
ans1 %= MOD;
}
printf("Case #%d: %lld\n",C++,ans);
}
return 0;
}
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 1100010
#define MOD 1000000007
int n,m;
int a[1010];
long long dp[1010][1010];
long long X,Y;
long long mi(long long x,long long a,int p)
{
long long ans = 1;
x = x % p;
while(a)
{
if(a&1)
ans = (ans * x) % p;
x = (x * x) % p;
a >>= 1;
}
return ans;
}
long long gcd(long long a,long long b)
{
int t,d;
if(b == 0)
{
X = 1;
Y = 0;
return a;
}
d = gcd(b,a%b);
t = X;
X = Y;
Y = t - (a / b) * Y;
return d;
}
int main()
{
int t,C = 1;
scanf("%d",&t);
gcd(2,MOD);
X += MOD;
while(t--)
{
scanf("%d",&n);
memset(dp,0,sizeof(dp));
for(int i = 1; i <= n; i++)
scanf("%d",&a[i]);
dp[1][1] = 1;
for(int i = 2; i < n; i++)
{
// if(a[i] == 1)
// dp[i][j+1] = dp[i-1][j];
// else
// dp[i][j+1] = (dp[i][j]*2 - dp[i-1][j] + MOD)%MOD;
if(a[i] == 1)
{
for(int j = 1; j <= i; j++)
dp[i][j] = dp[i-1][j-1];
}
else
{
for(int j = i-1; j >= 1; j--)
dp[i][j] = (dp[i][j+1]+dp[i-1][j])%MOD*X%MOD;
dp[i][1] = dp[i][1] * 2 % MOD;
}
}
long long ans = 0;
for(int i = 1; i < n; i++)
{
for(int j = 0; j < i; j++)
dp[n-1][i] = dp[n-1][i] * X % MOD;
ans += dp[n-1][i];
ans %= MOD;
}
printf("Case #%d: %lld\n",C++,ans);
}
return 0;
}