codeforces514E
Darth Vader and Tree
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
3 3
1 2 3
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的更多相关文章
随机推荐
- hdu 1342.. 复习广搜 顺便练习一下一个脑残的格式
In a Lotto I have ever played, one has to select 6 numbers from the set {1,2,...,49}. A popular stra ...
- C#判断字符串中含有多少个汉字
private void button1_Click(object sender, EventArgs e) { ArrayList itemList = new ArrayList(); CharE ...
- element 右键菜单
右键菜单 这是一个右键菜单的组件 <template> <div id="dropMenu" :style="style" style=&qu ...
- Go 操作 Mysql(一)
关于 Go 的标准库 database/sql 和 sqlx database/sql 是 Go 操作数据库的标准库之一,它提供了一系列接口方法,用于访问数据库(mysql,sqllite,oralc ...
- iOS - OC 使用运行时来获取并修改类
前言: Objective C的runtime技术功能非常强大,能够在运行时获取并修改类的各种信息,包括获取方法列表.属性列表.变量列表,修改方法.属性,增加方法,属性等等,本文对相 ...
- 2019.9.27,SAP成都研究院数字创新空间团队建设,射箭和游泳
2019年9月27日,秋高气爽,SAP成都研究院数字创新团队全体成员又迎来了一次团队建设活动.这次的主题是:射箭. 在正式活动之前,大家先享用了一顿泰式海鲜火锅: 吃饱喝足之后,我们来到了名为&quo ...
- Android应用查看本地数据库
使用Android Studio 视图==>工具窗口 == >Device File Explorer ==> 文件在 data/data目录下,你的应用程序报名,右键save as ...
- py map reduce filter 总结
array=[1,3,4,71,2] ret=[] for i in array: ret.append(i**2) print(ret) #如果我们有一万个列表,那么你只能把上面的逻辑定义成函数 d ...
- Scala配置环境变量Linux
1.下载.上传并解压scala-2.11.6.tgz 2.配置环境变量vim /etc/profile 增加如下代码: export SCALA_HOME=/usr/scala/scala-2.11. ...
- Lorenzo Von Matterhorn(map的用法)
http://www.cnblogs.com/a2985812043/p/7224574.html 解法:这是网上看到的 因为要计算u->v的权值之和,我们可以把权值放在v中,由于题目中给定的u ...