BZOJ1867[Noi1999]钉子和小球
原题链接:钉子和小球 。
先说DP:
DP方程极为简单,如果这个地方有钉子,那么下一层的左右钉子分别继承1/2的概率,如果没有钉子,那么下下层的钉子继承该处全部概率即可。
写出来是这样的:
if(a[i][j] == '*') a[i+1][j] += a[i][j] / 2,a[i+1][j+1] += a[i][j]/2; else a[i+2][j+1] += a[i][j];
当我美滋滋的写完,发现题目要求提交分数。
这还不简单,分母是2^n不就好了吗。
一键三连WA WA WA ~~~
分数结构体:
于是我去找了题解,发现有一个叫做分数结构体的东西。用于处理分数计算。
它的主要东西大概是这个:
struct node { long long up, down; node(long long _up = 0, long long _dn = 1) : up(_up), down(_dn){}; void reduction() { long long t = gcd(up, down); up /= t; down /= t; } void print() { cout << up << '/' << down; } } f[MAXN][MAXN]; node operator*(node a, node b) { node c = node(a.up * b.up, a.down * b.down); c.reduction(); return c; } node operator+(node a, node b) { long long t = gcd(a.down, b.down); node c = node(b.down / t * a.up + a.down / t * b.up, a.down / t * b.down); c.reduction(); return c; }
上面结构体里需要构造函数,否则计算时分母为0就崩了。
下面两个重载运算符。
在赋值的时候,要使用构造函数。不然编译不过去。(c++11是可以的但是BZOJ)
一个小坑点:
最后交的时候一直TLE,直到最后发现是在分母相乘时,因为先写分母相乘再约分导致爆long long,顺序调整一下就可以了。