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的更多相关文章
随机推荐
- 如何升级centos7 内核方法
关于内核说明: 版本性质:主分支ml(mainline),稳定版(stable),长期维护lt(longterm) 版本命名格式:“A.B.C" A代表内核版本号 B代表内核主版本号 C代表 ...
- 在论坛中出现的比较难的sql问题:17(字符分拆2)
原文:在论坛中出现的比较难的sql问题:17(字符分拆2) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有必要记录下来 ...
- js按钮频繁提交解决方案:
1.封装js: /// 函数节流 xhz.canRun = true; xhz.Throttling = function () { if (!xhz.canRun) { layer.msg('处理中 ...
- Python之网格搜索与检查验证-5.2
一.网格搜索,在我们不确定超参数的时候,需要通过不断验证超参数,来确定最优的参数值.这个过程就是在不断,搜索最优的参数值,这个过程也就称为网格搜索. 二.检查验证,将准备好的训练数据进行平均拆分,分为 ...
- mac下卸载android studio
Execute these commands from the terminal rm -Rf /Applications/Android\ Studio.app rm -Rf ~/Library/P ...
- Mac 下编译 Hadoop
Mac 下编译 Hadoop-2.9.2 系统环境 系统: Mac OS_10.14.4 maven: Apache Maven 3.6.0 jdk: jdk_1.8.0_201 ProtocolBu ...
- jQuery标签操作
样式操作 样式类操作 //添加指定的css类名 $('元素选择器')addClass('类名'); //移除指定的css类名 removeClass(); //判断样式存不存在 hasClass(); ...
- 解决在web.xml中配置server服务器启动失败问题
一.问题"Server Tomacat v8.5 Server at locallhost failed to start" 二.解决方法:删除注释@webServlet 三.分析 ...
- MongoDB 无法启动
提示 mongodb Mongod complains that there is no /data/db folder!! 解决方法:http://stackoverflow.com/questio ...
- RestFramework之序列化组件
一.restframework的序列化组件的使用 1.导入序列化组件与模型类 from rest_framework import serializers from app01.models impo ...