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的更多相关文章
随机推荐
- 【转发】Java split()用法
特殊情况有 * ^ : | . \ 一.单个符号作为分隔符 String address="上海\上海市|闵行区\吴中路"; String[] splitAddress=addr ...
- MP4数据封装格式
一 .MP4 https://blog.csdn.net/sdsszk/article/details/90719075 MP4 由很多个ATOM 嵌套构成,主要的ATOM包括 [ftyp] ...
- 关于微信小程序分享/转发功能的实现方法
实现微信小程序分享,可以有两个入口: 1. 小程序右上角菜单自带的分享 这个入口是默认关闭的,需要在当前页面中调用showShareMenu方法,开启分享 onLoad: function () { ...
- vue父子组件传值例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- IDEA提示不区分大小写设置
File–>Settings–>Editor–>General–>Code Completion–>Mach case的勾取消掉就可以了 取消勾后效果如下
- rabbitmq笔记(一)rabbitmq简介及基础
一.消息组件 如果从消息组件来讲主要划分位两类: 1.JMS组件:ActiveMQ(慢): 2.AMQP组件(协议):性能是最高的, 而AMQP有两个主要的开源: 1)RabbitMQ:使用最广泛,速 ...
- mysql主从部署
一.安装环境 1.系统环境 系统 IP 主机名 说明 server_id centos6.7 192.168.0.173 master 数据库:主 173 centos6.7 192.168.0.1 ...
- SQL SERVER-端口Port
Quick cheat sheet for port numbers used by SQL Server services or services that SQL Server may depen ...
- xlsxwriter写入Excel文件
#coding=utf-8 import xlsxwriter #加载包 myWorkbook = xlsxwriter.Workbook(opath+'/'+file_name+'.xlsx') # ...
- 学习使用Django2 前台页面展示
Django 2.1 python 3.7 创建一个虚拟环境 python -m venv 虚拟环境名称 进入虚拟环境 下载django pip install django==2.1 创 ...