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的更多相关文章
随机推荐
- idea 中 下载源码:Sources not download for:
使用idea 下载源码出现:Sources not found for: 解决方案:在对应的pom.xml 文件中打开 terminal,执行 mvn命令: mvn dependency:source ...
- C#-Json-抽象类的反序列化
引用: using System; using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Lin ...
- C# SpinLock用法。
class Program { static void Main(string[] args) { ; ]; Stopwatch sp = new Stopwatch(); sp.Start(); / ...
- (面试题)请用C语言实现在32位环境下,两个无符号长整数相加的函数,相加之和不能存储在64位变量中
分析:长整数相加,将结果分为高位和低位部分,分别保存在两个32整数中. 比如:unsigned int a = 0xFFFFFFFF, unsigned int b = 0x1, 结果用unsigne ...
- Python windows环境 搭建问题
环境安装包下载地址: https://pan.baidu.com/s/1bnVhHMZ?fid=642139599707514 百度地址: http://sw.bos.baidu.com/sw-sea ...
- code first从入门到伪精通
新入职一家公司,虽然之前也用ef,但是方式不一样,之前用的db,现在用代码先行的code,基于现有公司基本项目框架都是用的code,所以一步登顶,从最实战的角度去操作code,心颤的很,废话不多说,开 ...
- 读书笔记——《redis入门指南(第2版)》第七章 持久化
7 持久化 在一些情况下,我们会希望Redis 在重启后能够保证数据不丢失,例如: 1·将Redis 作为数据库使用时. 2·将Redis 作为缓存服务器,有可能出现的缓存雪崩会使服务无法响应. 这时 ...
- Java泛型全解析【接口、类、封装类型】
目录 1.导读 2.为何需要泛型? 3.泛型的定义格式 3.泛型的好处 4.什么时候使用泛型? 5.泛型的擦除 6.泛型的补偿 7.泛型的应用 7.1[泛型类] ...
- 记一次oracle 11g数据导入
1.ORACLE数据库数据导入到测试库环境 172.15.1.51 root kic@test 172.15.1.52 root 一般先将数据导入52的环境(配置比较低),再将数据导入51的环境(本 ...
- ubuntu 修改环境变量(PATH)
1.什么是环境变量(PATH) 在Linux中,在执行命令时,系统会按照PATH的设置,去每个PATH定义的路径下搜索执行文件,先搜索到的文件先执行. 我们知道查阅文件属性的指令ls 完整文件名为:/ ...