Darth Vader and Tree

CodeForces - 514E

When Darth Vader gets bored, he sits down on the sofa, closes his eyes and thinks of an infinite rooted tree where each node has exactly n sons, at that for each node, the distance between it an its i-th left child equals to di. The Sith Lord loves counting the number of nodes in the tree that are at a distance at most x from the root. The distance is the sum of the lengths of edges on the path between nodes.

But he has got used to this activity and even grew bored of it. 'Why does he do that, then?' — you may ask. It's just that he feels superior knowing that only he can solve this problem.

Do you want to challenge Darth Vader himself? Count the required number of nodes. As the answer can be rather large, find it modulo 109 + 7.

Input

The first line contains two space-separated integers n and x (1 ≤ n ≤ 105, 0 ≤ x ≤ 109) — the number of children of each node and the distance from the root within the range of which you need to count the nodes.

The next line contains n space-separated integers di (1 ≤ di ≤ 100) — the length of the edge that connects each node with its i-th child.

Output

Print a single number — the number of vertexes in the tree at distance from the root equal to at most x.

Examples

Input
3 3
1 2 3
Output
8

Note

Pictures to the sample (the yellow color marks the nodes the distance to which is at most three)

给出一个每个节点有n个孩子的多叉树,父亲到第i个孩子有固定的长度,问到根节点的距离不超过x的节点的数目。
1 <= n <= 1e5; 0 <= x <= 1e9; 1 <= di <= 100 Mod=1e9+7

sol:有一个较显然的dp,dp[i]表示深度为i的点的个数,这样就有了一个很裸的暴力

/*
给出一个每个节点有n个孩子的多叉树,父亲到第i个孩子有固定的长度,问到根节点的距离不超过x的节点的数目。
1 <= n <= 1e5; 0 <= x <= 1e9; 1 <= di <= 100 Mod=1e9+7
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
ll s=; bool f=; char ch=' ';
while(!isdigit(ch)) {f|=(ch=='-'); ch=getchar();}
while(isdigit(ch)) {s=(s<<)+(s<<)+(ch^); ch=getchar();}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<) {putchar('-'); x=-x;}
if(x<) {putchar(x+''); return;}
write(x/); putchar((x%)+'');
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const ll N=,Mod=;
ll n,m,d[N];
ll dp[N],f[];
inline void Ad(ll &x,ll y)
{
x+=y; x-=(x>=Mod)?Mod:;
}
int main()
{
freopen("codeforces514E_data.in","r",stdin);
int i,j,k;
R(n); R(m);
for(i=;i<=n;i++) f[d[i]=read()]++; sort(d+,d+n+); n=unique(d+,d+n+)-d-;
dp[]=;
for(i=;i<=m;i++)
{
for(j=;j<=min(i,);j++) Ad(dp[i],dp[i-j]*f[j]%Mod);
}
ll ans=;
for(i=;i<=m;i++) Ad(ans,dp[i]);
Wl(ans);
return ;
}

然后发现di很小,转移方程可以用矩阵快速幂优化,发现转移dp[x]时有用的就是dp[x-100]~dp[x],而在转移dp[x+1]时有用的就是dp[x-99]~dp[x+1]了,而转移就是向暴力写的dp一样,每次只要转移最后一位就是了,前面的都可以搬过来,所以矩阵就可以推了

[0 0 0 ... 0 0 f[100] f[100]]
[1 0 0 ... 0 0 f[99] f[99]    ]
[0 1 0 ... 0 0 f[98] f[98]    ]
[0 0 1 ... 0 0 f[97] f[97]    ]
...
[0 0 0 ... 0 1 f[1] f[1]        ]
[0 0 0 ... 0 0 0 1              ]

/*
给出一个每个节点有n个孩子的多叉树,父亲到第i个孩子有固定的长度,问到根节点的距离不超过x的节点的数目。
1 <= n <= 1e5; 0 <= x <= 1e9; 1 <= di <= 100 Mod=1e9+7
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
ll s=; bool f=; char ch=' ';
while(!isdigit(ch)) {f|=(ch=='-'); ch=getchar();}
while(isdigit(ch)) {s=(s<<)+(s<<)+(ch^); ch=getchar();}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<) {putchar('-'); x=-x;}
if(x<) {putchar(x+''); return;}
write(x/); putchar((x%)+'');
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const ll N=,Mod=;
ll n,m,dp[N],f[N],Qzh[N];
ll a[N][N],b[N][N],c[N][N],ans[N][N];
inline void Ad(ll &x,ll y)
{
x+=y; x-=(x>=Mod)?Mod:;
}
int main()
{
freopen("codeforces514E_data.in","r",stdin);
freopen("my.out","w",stdout);
int i,j,k;
R(n); R(m);
for(i=;i<=n;i++) f[read()]++;
dp[]=Qzh[]=;
for(i=;i<=;i++)
{
for(j=;j<=i;j++) Ad(dp[i],dp[i-j]*f[j]%Mod);
Qzh[i]=Qzh[i-]; Ad(Qzh[i],dp[i]);
}
if(m<=)
{
Wl(Qzh[m]); return ;
}
// for(i=0;i<=100;i++) W(dp[i]); puts("");
for(i=;i<=;i++) ans[][i]=dp[i]; ans[][]=Qzh[];
for(i=;i<=;i++) a[i][i]=;
for(i=;i<=;i++) b[i][i-]=; b[][]=;
for(i=;i<=;i++) b[i][]=b[i][]=f[-i];
// for(i=1;i<=101;i++,puts("")) for(j=1;j<=101;j++) W(b[i][j]);
// memmove(b,a,sizeof b);
int oo=m-;
while(oo)
{
if(oo&)
{
memset(c,,sizeof c);
for(i=;i<=;i++) for(j=;j<=;j++) for(k=;k<=;k++)
{
Ad(c[i][j],1ll*a[i][k]*b[k][j]%Mod);
}
memmove(a,c,sizeof a);
}
oo>>=;
memset(c,,sizeof c);
for(i=;i<=;i++) for(j=;j<=;j++) for(k=;k<=;k++)
{
Ad(c[i][j],1ll*b[i][k]*b[k][j]%Mod);
}
memmove(b,c,sizeof b);
}
memset(c,,sizeof c);
for(i=;i<=;i++) for(j=;j<=;j++) for(k=;k<=;k++)
{
Ad(c[i][j],ans[i][k]*a[k][j]%Mod);
}
memmove(ans,c,sizeof ans);
Wl(ans[][]);
return ;
}

codeforces514E的更多相关文章

随机推荐

  1. 一行代码实现Vue微信支付,无需引用wexin-sdk库,前后端分离HTML微信支付,无需引用任何库

    前后端分离项目实现微信支付的流程: 1:用户点击支付 2:请求服务端获取支付参数 3:客户端通过JS调起微信支付(微信打开的网页) * 本文主要解决的是第3步,视为前两步已经完成,能正确拿到支付参数, ...

  2. mysql授权单个表权限

    mysql> create user haochengtest@'%' identified by 'haocheng.123'; Query OK, 0 rows affected (0.01 ...

  3. windows下批处理保留指定日期下的文件

    @echo offchcp 65001setlocal enabledelayedexpansion ::设置操作路径set "pic_dir=D:\465"echo 开始清理.. ...

  4. 【转载】Sqlserver根据生日计算年龄

    在Sqlserver中,可以根据存储的出生年月字段计算出该用户的当前年龄信息,主要使用到DateDiff函数来实现.DateDiff函数的格式为DATEDIFF(datepart,startdate, ...

  5. 类中变量私有化和调用:__x和getx/setx或者property

    __xx:双前置下划线,子类不可继承属性.方法,父类私有. 详见:https://www.cnblogs.com/andy9468/p/8299448.html 例子1:隐藏数据:私有化后,用get和 ...

  6. scikit-learn中的机器学习算法封装——kNN

    接前面 https://www.cnblogs.com/Liuyt-61/p/11738399.html 回过头来看这张图,什么是机器学习?就是将训练数据集喂给机器学习算法,在上面kNN算法中就是将特 ...

  7. ES6 正则扩展

    一.新增 flags 属性 ES6 为正则表达式新增了flags属性,会返回正则表达式的修饰符. // ES5 的 source 属性 // 返回正则表达式的正文 /abc/ig.source // ...

  8. MySQL进阶10--DML数据操纵预言: insert/delete/update --多表连接修改/.多表连接删除/多表连接查询-- truncate 和 delete的区别

    /* DML -- 数据操纵预言: insert/delete/update */ #一: 插入语句 /* 语法1: insert into 表名(列名,..,列名....) values(值1,值2 ...

  9. 20 区分webpack中导入vue和普通网页使用script导入Vue的区别

    回顾包的查找规则: 1.找项目根目录中有没有node_modules的文件夹 2.在node_modules中根据包名,找对应的vue文件夹 3.在vue文件夹中,找一个叫做package.json的 ...

  10. matlab(6) Regularized logistic regression : plot data(画样本图)

    Regularized logistic regression :  plot data(画样本图) ex2data2.txt 0.051267,0.69956,1-0.092742,0.68494, ...