美文网首页
PROB: nocows

PROB: nocows

作者: SylviaShen | 来源:发表于2017-08-13 11:04 被阅读0次

题目来自 USACO
题目翻译见 nocow


/*
ID: 
LANG: C++
TASK: nocows
*/

#include <cstdio>
#include <cstdlib>
#define maxN 200
#define maxH 100

int main(){
    FILE *fin = fopen("nocows.in", "r");
    FILE *fout = fopen("nocows.out", "w");

    int N, H; //节点个数,树的高度
    fscanf(fin, "%d %d", &N, &H);

    int varient[maxN][maxH] = {0}; //varient[n][h]是n个节点h高度的树的个数
    varient[1][1] = 1;
    varient[3][2] = 1;
    int h, n, nlow = 3, nhi = 3, left, right;
    for(h = 3; h <= H; h ++){ //高度为h
        nlow += 2;
        // nhi = nhi * 2 + 1;  //这里到n = 32会溢出哦,不过早在2^n-1超过N就已经不起作用了
        if(h < 20) nhi = nhi * 2 + 1;
        for(n = nlow; n <= nhi && n <= N; n += 2){ //节点数n
            for(left = 1; left < n - 1; left += 2){ //左子树的节点数
                right = n - 1 - left; 
                if(varient[left][h - 1]){ //左子树高度为h-1, 右=[1,h-1]
                    for(int rh = 1; rh <= h - 1; rh ++)
                        if(varient[right][rh])
                            varient[n][h] += varient[left][h - 1] * varient[right][rh];
                            varient[n][h] %= 9901; //等全部加完又溢出了
                }
                if(varient[right][h - 1]){ //右子树高度为h-1, 左=[1,h-1)
                    for(int lh = 1; lh < h - 1; lh ++)
                        if(varient[left][lh])
                            varient[n][h] += varient[left][lh] * varient[right][h - 1];
                            varient[n][h] %= 9901;
                }
            }
            varient[n][h] %= 9901;
        }
    }

    // for(int i = 1; i < H; i ++){
    //     fprintf(fout, "\nh = %d--------------------------------------------\n", i);
    //     for(int j = 1; j < N; j ++){
    //         fprintf(fout, "%d\t", varient[j][i]);
    //     }
    // }
    
    fprintf(fout, "%d\n", varient[N][H]);

    return 0; 
    
}
   Test 1: TEST OK [0.000 secs, 4176 KB]
   Test 2: TEST OK [0.000 secs, 4176 KB]
   Test 3: TEST OK [0.000 secs, 4176 KB]
   Test 4: TEST OK [0.000 secs, 4176 KB]
   Test 5: TEST OK [0.000 secs, 4176 KB]
   Test 6: TEST OK [0.000 secs, 4176 KB]
   Test 7: TEST OK [0.000 secs, 4176 KB]
   Test 8: TEST OK [0.000 secs, 4176 KB]
   Test 9: TEST OK [0.014 secs, 4176 KB]
   Test 10: TEST OK [0.014 secs, 4176 KB]
   Test 11: TEST OK [0.014 secs, 4176 KB]
   Test 12: TEST OK [0.014 secs, 4176 KB]

dp

经点拨才有思路。二叉树这么漂亮的递归结构,想想也是很容易用前面已经计算过的结论的。然后就迷在到底怎么用了,越想越复杂,后来发现考虑第一个分叉,分成左右两个子树,较大的那个高度是h-1,每个子树的节点数也小于n,就足以使用前面算的结果了。

溢出

第一次遇到数字极大,结果要取模的问题。print一下发现很快就遍布着负数,果然溢出。试着用long long int 也不够。嗯果然是不打算让我算准确数值的。有一个很常用的结论(a % n) * (b % n) == (a * b) % n,所以每一个值都取下模就好了。

于是又挂了,print一下发现我加完再取模又就已经溢出了,那就每加一次就取模吧。

又一个测试挂了,发现前面的nhi,节点数的上界,在高度为32的时候溢出了,又一个果然……不过这个上界早就没用了,溢出之前停掉好了。

最后

本来以为后面数大了需要剪枝,结果不需要就已经这么快了,那就算了……
本来也是N * H ^ 2的复杂度,没多大。我这里好像是N * H ^ 3,因为比官答的累加复杂了点,把rhlh过了一遍,不过数字小,还是很快……

相关文章

  • PROB: nocows

    题目来自 USACO题目翻译见 nocow dp 经点拨才有思路。二叉树这么漂亮的递归结构,想想也是很容易用前面已...

  • numpy篇

    Numpy 2018-05-21 numpy.prob:numpy.prob(a, axis=None, dtyp...

  • 负二项分布

    dnbinom(x, size, prob):返回发生x次失败事件的概率rnbinom(n, size, prob...

  • PROB: cowtour

    题目来自 USACO题目翻译见 NOCOW 超时的暴搜 这道题一看也是很清楚了,求一个连通部分的直径,那就肯定是 ...

  • PROB: money

    题目来自 USACO题目翻译见 NOCOW 思路 用给定的货币系统,求某值有多少种组合。 几乎就是个背包问题了。只...

  • PROB: concom

    题目来自 USACO题目翻译见 NOCOW 最初的思路 看到这道题我是很懵的,就是让我自己手算,我也不知道该怎么算...

  • PROB: ttwo

    题目来自 USACO题目翻译见 NOCOW 思路 题目很软萌,看懂规则模拟就好了。可能是我代码能力下降太快了,写了...

  • PROB:zerosum

    题目来自 USACO题目翻译见 nocow 题目很简单,自己都说了让我们暴搜。 运算符最多 8 个,每个 3 种,...

  • 韦小绿

    很多很多 grov prob am

  • linear algebra week3 matrices

    Matrices, vectors, and solving simultaneous equation prob...

网友评论

      本文标题:PROB: nocows

      本文链接:https://www.haomeiwen.com/subject/gwisrxtx.html