Hdu 5819 Knights ★

第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=ji1f(i1,k)(21)kj+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(i1,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}^jj=1n1f(n1,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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值