51nod1582-n叉树

1582 n叉树

有一棵n叉树,深度是无限的,每个结点有n个儿子。从左到右编号为1到n号儿子,第i号儿子离该结点的距离是di。现在要统计一下距离根结点不超过x的结点有多少个。

数字比较大对 109 + 7 取余后输出。

样例解释:

图中黄色的结点是距离根不超3的。

Input

单组测试数据。
第一行有两个整数n和x (1≤n≤10^5,0≤x≤10^9),表示每个结点的儿子数目,以及上文提到的x。
第二行有n个整数d1,d2,d3,…,dn (1≤di≤100)。

Output

输出结果占一行。

Input示例

样例输入1
3 3
1 2 3

Output示例

样例输出1
8暴力DP很好想,f[i]表示到根节点深度为i的有几个,f[i]=sigma(f[i-j]*cnt[j]),j=1->100这样就可以用个矩阵来描述啦,意会一下

放上大佬NBC的代码就是上面的思路,对于边界的情况我不是很懂,如有大佬看懂请尽快发表。
#include <cstdio>
#include<iostream>
using namespace std;
int I()
{
    int r = 0, c;
    do c = getchar(); while (c < 48 || c > 57);
    do r = (r << 3) + r + r + (c - 48), c = getchar(); while (c > 47 && c < 58);
    return r;
}
const long long MOD = 1000000007;
int N, X, cnt[101];
long long ans[101], bit[101][101];
void push()
{
    static long long tmp[101];
    for (int i = 0; i < 101; i++)
    {
        tmp[i] = 0;
        for (int j = 0; j < 101; j++)
            if ((tmp[i] += bit[i][j] * ans[j]) > 8223372024854775771LL)
                tmp[i] %= MOD;
    }
    for (int i = 0; i < 101; i++)
        ans[i] = tmp[i] % MOD;
}
void twice()
{
    static long long tmp[101][101];
    for (int i = 0; i < 100; i++)
        for (int j = 0; j < 100; j++)
        {
            tmp[i][j] = 0;
            for (int k = 0; k < 101; k++)
                if ((tmp[i][j] += bit[i][k] * bit[k][j]) > 8223372024854775771LL)
                    tmp[i][j] %= MOD;
        }
    for (int i = 0; i < 101; i++)
        for (int j = 0; j < 101; j++)
            bit[i][j] = tmp[i][j] % MOD;
}
int main()
{
    N = I(), X = I();
    for (int i = 1; i <= N; i++)
        cnt[I()]++;
    ans[0] =ans[100] = 1;
    for (int i = 0; i < 99; i++)
        bit[i + 1][i] = 1;
    for (int i = 0; i < 100; i++)
        bit[0][i] = cnt[i + 1];
    bit[0][100] = bit[100][100] = 1;
    for(int i=0;i<=50;i++)
    {
        for(int j=0;j<=50;j++)
            cout<<bit[i][j]<<‘ ‘;
        cout<<endl;
    }
    for (; X; X >>= 1)
    {
        if (X & 1)
            push();
        twice();
    }
    printf("%lld\n", ans[0]);
    return 0;
}
时间: 2024-10-18 06:43:18

51nod1582-n叉树的相关文章

线索化二叉树

二叉树的遍历运算是将二叉树中节点按一定规律线性化的过程,当二叉链表作为存储结构时,只能找到节点的左.右孩子信息,而不能直接得到节点在遍历序列中的前驱和后继信息.线索化二叉树能够解决这样的问题,将二叉链表中的空指针域填上相应节点的遍历前驱或后继节点的地址,而前驱和后继的地址只能在动态的遍历过程中才能得到.可以按照不同的遍历次序进行线索化,先序遍历.遍历过程中的节点的前驱.后继信息保存下来.下面是线索化二叉树节点结构: 其中,_left和_right表示节点的左.右孩子,_leftTag和_righ

选课 树形DP+多叉树转二叉树+dfs求解答案

问题 A: 选课 时间限制: 1 Sec  内存限制: 128 MB提交: 6  解决: 3[提交][状态][答疑][寄存][题解] 题目描述 大 学里实行学分.每门课程都有一定的学分,学生只要选修了这门课并考核通过就能获得相应的学分.学生最后的学分是他选修的各门课的学分的总和. 每个学生都要选择规定数量的课程.其中有些课程可以直接选修,有些课程需要一定的基础知识,必须在选了其它的一些课程的基础上才能选修.例如,<数据结 构>必须在选修了<高级语言程序设计>之后才能选修.我们称&l

平衡的三叉树

去年3月份,写了一个平衡的三叉树算法包,还写了一个基于逆向最大匹配算法的中文分词算法包.现在,将平衡的三叉树算法包上传.首先看一下包结构: 1.chinese.utility.cfg代码: package chinese.utility.cfg; /** * 获得主词典.量词词典以及扩展词典和扩展停词词典的路径 * @author TongXueQiang * @date 2015/11/25 * @since 1.8 */public interface Configuration {    

中序线索化二叉树

中序线索化二叉树 1 void Tree::_inTree(Node * root, Node * &pre) { 2 if (root == NULL) { // 结点为空, 1:二叉树为空 2:已到达右子树的最后一个右结点的 rchild 3 return; 4 } 5 _inTree(root->lchild, pre); // 到达当前结点的左子树的底部左结点 6 if (root->lchild == NULL) { 7 root->ltag = nChild; //

数据结构 树的创建(线索化二叉树)

//二叉树的线索化 #include<stdio.h> #include<stdlib.h> #include<string.h> //定义二叉树线索化节点 typedef struct _TreeNode{ char data; char lefttag;//0表示没有线索化,1表示线索化---每次创建节点都会初始化 所以所有节点默认都是0 char righttag; struct _TreeNode * leftchild; struct _TreeNode *

BZOJ 3684 大朋友和多叉树 FFT+拉格朗日反演

题目大意:给定n和集合S,求满足下列要求的多叉树的个数: 1.每个非叶节点的子节点数量在集合S中 2.每个叶节点的权值为1,每个非叶节点的权值为子节点权值之和 3.根节点的权值为n 注意每个节点的子节点有顺序 令fi表示根节点权值为i的神犇二叉树个数,F(x)为fi的生成函数,C(x)为S的生成函数,那么有: F(x)=∑i∈SFi(x)+x F(x)=C(F(x))+x F(x)?C(F(x))=x 不妨令G(x)=1?C(x) 那么有: G(F(x))=x 因此F(x)是G(x)的复合逆 拉

HDU 6121 Build a tree(完全K叉树)

http://acm.hdu.edu.cn/showproblem.php?pid=6121 题意:给你一颗完全K叉树,求出每棵子树的节点个数的异或和. 思路: 首先需要了解一些关于完全K叉树或满K叉树的一些知识: 对于每棵子树,只有三种情况: ①是满K叉树  ②不是满K叉树  ③叶子节点 并且非满K叉树最多只有一个,所以只需要将它进行特殊处理,具体看代码吧,说不清楚.代码参考了http://blog.csdn.net/my_sunshine26/article/details/77200282

三叉树

package com.txq.ternaryTree; import java.util.HashSet;import java.util.Set;/** * 自定义三叉树 * @author TongXueQiang * @date 2016/03/03 * @since JDK 1.7 */public class TernaryTree { // 根节点 private static Node root; // 存储前缀匹配结果的集合 private Set<String> resul

HDU3974 Assign the task(多叉树转换为线段+线段树区间染色)

题目大意:有n个人,给你他们的关系(老板和员工),没有直属上司的人就是整个公司的领导者,这意味着n个人形成一棵树(多叉树).当一个人被分配工作时他会让他的下属也做同样的工作(并且立即停止手头正在做的工作),题目会询问你其中某个人正在做的工作. 解题思路:其实从"一个人分配他的下属做一样的工作"这里就可以看出来了,这相当于让一块区间的人都做一样的事,就是线段树区间染色问题.但不能使用线段树,要先将多叉树铺展开,将节点映射到线段上.把每个人的管理区段找出来(把属于同一个人管的放一起,上司放