bzoj千题计划189:bzoj1867: [Noi1999]钉子和小球

http://www.lydsy.com/JudgeOnline/problem.php?id=1867

 

dp[i][j] 落到(i,j)的方案数

dp[i][j]=0.5*dp[i-1][j]   [(i-1,j)位置有钉子] + 0.5*dp[i-1][j-1]    [(i-1.j-1)位置有钉子] + dp[i-1][j-2]    [(i-1,j-2)位置没有钉子]

 

#include<cstdio>
#include<iostream>

using namespace std;

typedef long long LL;

#define N 52

bool nail[N][N];

LL getgcd(LL a,LL b) { return !b ? a : getgcd(b,a%b); }

struct Fraction
{
    LL molecule,denominator;

    void operator = (int p)
    {
        molecule=p;
        denominator=1;
    }
    
    Fraction operator * (Fraction p)
    {
        Fraction c;
        c.molecule=molecule;
        c.denominator=denominator<<1;
        LL gcd=getgcd(c.molecule,c.denominator);
        c.molecule/=gcd;
        c.denominator/=gcd;
        return c;
    }
    
    void operator += (Fraction p)
    {
        if(!denominator) 
        {
            *this=p;
            return;
        }
        Fraction c;
        LL gcd=getgcd(denominator,p.denominator);
        c.denominator=denominator/gcd*p.denominator;
        c.molecule=c.denominator/denominator*molecule+c.denominator/p.denominator*p.molecule;
        *this=c;
    }
    
    bool have()
    {
        return denominator;
    }
    
    void print()
    {
        if(!molecule) denominator=1;
        cout<<molecule<<'/'<<denominator;
    }
    
}half;

Fraction dp[N][N];

char getc()
{
    char c;
    while(1)
    {
        c=getchar();
        if(c=='*'||c=='.') return c;
    }
}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    char c;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=i;++j)
        {
            c=getc();
            if(c=='*') nail[i][j]=true;
        }
    dp[1][1]=1;
    for(int i=2;i<=n+1;++i)
        for(int j=1;j<=i;++j)
        {

            if(nail[i-1][j-1] && dp[i-1][j-1].have()) dp[i][j]+=dp[i-1][j-1]*half;
            if(nail[i-1][j] && dp[i-1][j].have()) dp[i][j]+=dp[i-1][j]*half;
            if(!nail[i-2][j-1] && dp[i-2][j-1].have()) dp[i][j]+=dp[i-2][j-1];
        }
    dp[n+1][m+1].print();
}

 

1867: [Noi1999]钉子和小球

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 880  Solved: 355
[Submit][Status][Discuss]

Description

Input

第1行为整数n(2<=n<=50)和m(0<=m<=n)。以下n行依次为木板上从上至下n行钉子的信息,每行中‘*’表示钉子还在,‘.’表示钉子被拔去,注意在这n行中空格符可能出现在任何位置。

Output

仅一行,是一个既约分数(0写成0/1),为小球落在编号为m的格子中的概pm。既约分数的定义:A/B是既约分数,当且仅当A、B为正整数且A和B没有大于1的公因子。

Sample Input

5 2






Sample Output

7/16
posted @ 2018-01-04 09:13  TRTTG  阅读(182)  评论(0编辑  收藏  举报