您的位置:首页 > 其它

矩阵快速幂DP Darth Vader and Tree : CodeForces - 514E

2017-06-14 13:43 537 查看

题目:CodeForces - 514E

time limit per test2 seconds

memory limit per test256 megabytes

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 ≤ 10^5, 0 ≤ x ≤ 10^9) — 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个孩子,每个孩子距离父亲节点的距离为di.求距离根节点距离<=x的节点个数.

思路:

利用di<=100做DP.f[i]表示到根节点距离<=i的节点个数.记所有di=j的个数为cnt[j],则

f[i]=∑j=1100f[i−j]∗cnt[j]+1

但是这样还不够,以为i的范围很大,不能用单纯的for循环来求解,这时候应该想到利用矩阵来做矩阵快速幂.

构造一个矩阵K使得[f1,f2,f3,…f100]*K=[f2,f3,f4,…,f101].要能够快速幂K肯定是个正方形矩阵.所以可以大致得到上面的矩阵公式.然后下面就是构造K矩阵的问题了.

由f[2]=f[1]*c[1]+1 f[3]=f[1]*c[2]+f[2]*c[1]+1 f[101]=f[1]*c[100]+f[2]*c[99]+…+f[100]*c[1]+1易知K的初步构造如下:

⎡⎣⎢⎢⎢⎢⎢⎢c100...0c2c10...0c3c2c1...0............0c100c99c88...c1⎤⎦⎥⎥⎥⎥⎥⎥

显然这样还不够,因为缺少了公式最后的”+1”,假设原矩阵是A*K=B的话,令A多一列变为[A,1],令K多一行一列,则K应该变为:

⎡⎣⎢⎢⎢⎢⎢⎢c100...0c2c10...0c3c2c1...0............0c100c99c88...c1⎤⎦⎥⎥⎥⎥⎥⎥→⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢c100...01c2c10...01c3c2c1...01............01c100c99c88...c11000001⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥

然后A*K=B的矩阵就构造完成了[f1,f2,f3,…f100,1]*K=[f2,f3,f4,…,f101,1].要求Fn,则计算A∗Kn−100即可.

十个利用矩阵乘法解决的经典题目

代码:

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
// head

typedef vector<ll> VL;
typedef vector<VL> matrix;
matrix mul(const matrix &a,const matrix &b) {
int n=SZ(a);
matrix c(n,VL(n,0));
rep(i,0,n) rep(j,0,n) rep(k,0,n) c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mod;
return c;
}
void multo(matrix &a,const matrix &b) {
int n=SZ(a);
matrix c(n,VL(n,0));
rep(i,0,n) rep(j,0,n) rep(k,0,n) c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mod;
rep(i,0,n) rep(j,0,n) a[i][j]=c[i][j];
}
matrix add(const matrix &a,const matrix &b) {
int n=SZ(a);
matrix c(n,VL(n,0));
rep(i,0,n) rep(j,0,n) {
c[i][j]=a[i][j]+b[i][j];
if (c[i][j]>=mod) c[i][j]-=mod;
}
return c;
}
void addto(matrix &a,const matrix &b) {
int n=SZ(a);
rep(i,0,n) rep(j,0,n) { a[i][j]+=b[i][j]; if (a[i][j]>=mod) a[i][j]-=mod;}
}
matrix unit(int n,int w=1) {
matrix c(n,VL(n,0));
rep(i,0,n) c[i][i]=w;
return c;
}
matrix powmod(matrix a,ll b) {
int n=SZ(a);
matrix res=unit(n);
for (;b;b>>=1) { if(b&1) multo(res,a);multo(a,a);}
return res;
}
matrix powsmod(matrix a,ll b) {
int n=SZ(a);
matrix res=unit(n),_a=a;
int k=0;for (;b>>k;k++);--k;
while(--k>=0) {
addto(a,unit(n));multo(res,a);
addto(a,unit(n,-1));multo(a,a);
if ((b>>k)&1) multo(res,_a),addto(res,unit(n)),multo(a,_a);
}
return res;
}
void print(const matrix &a) {
int n=SZ(a);
rep(i,0,n) {rep(j,0,n) cout<<a[i][j]<<" ";puts("");}
puts("");
}

int n,x,p,cnt[110];
int main() {
scanf("%d%d",&n,&x);
rep(i,0,n) {
scanf("%d",&p);
cnt[p]++;
}
matrix base=unit(102,0);
base[101][101]=1;
rep(i,0,100) base[i][i+1]=1;
rep(i,1,100+1) base[i-1][0]=cnt[i];
base[101][0]=1;
base=powmod(base,x+1);
printf("%I64d\n",base[101][0]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp 矩阵快速幂