题面比较文艺。
大意:给一棵树,这个树有无限个节点。对于每个点,都有n个儿子,第i个儿子与这个点的距离为
di
。问这棵树有多少个点离根的距离不超过x。
首先可以列出一个DP:
f[i]=∑nj=1f[i−dj]
,边界是
f[0]=1
。
似乎不是那么好做。但是注意到,
di<=100
,这意味着DP可以简化一下,变成连续的;
f[i]=∑100j=1f[i−j]∗cnt[j]
,其中j表示有多少条边权为j的边。要求的答案是
∑xi=0f[i]
,cnt可以预处理出来,接下来就是很经典的矩阵快速幂啦!
令
s[i]=∑1<=j<=if[j]
。设
F=(f[1]f[2]...f[100]s[100])
有伴随矩阵
A=⎛⎝⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜0100...000010...000001...00..................0000...10cnt[100]cnt[99]cnt[98]cnt[97]...cnt[1]0cnt[100]cnt[99]cnt[98]cnt[97]...cnt[1]1⎞⎠⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟
这个是显然的。左半部分是移位用的,倒数第二列用来计算新的f值,最后一列用新的f值加上s得到新的s值。
这样答案就是 FAx−100 的最后一个位。
当然前面要DP预处理一下,然后判断一下,再跑矩乘。
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i = a , _ = b ; i <= _ ; i ++)
#define per(i,a,b) for(int i = a , _ = b ; i >= _ ; i --)
#define For(i,a,b) for(int i = a , _ = b ; i < _ ; i ++)
inline int rd() {
char c = getchar();
while (!isdigit(c)) c = getchar() ; int x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x;
}
const int mod = 1000000007;
typedef long long ll;
inline int mul(int a , int b) { return (ll) a * b % mod; }
struct Matrix {
int a[101][101];
Matrix() { memset(a , 0 , sizeof a) ; }
friend Matrix operator*(Matrix&A , Matrix&B) {
Matrix C = Matrix();
For (i , 0 , 101) For (j , 0 , 101) For (k , 0 , 101)
(C.a[i][j] += mul(A.a[i][k] , B.a[k][j])) %= mod;
return C;
}
}A , B , T;
int n , x , cnt[101] , f[101];
void input() {
n = rd() , x = rd();
rep (i , 1 , n) cnt[rd()] ++;
}
void init() {
f[0] = 1;
rep (i , 1 , 100)
rep (j , 1 , i) (f[i] += mul(f[i - j] , cnt[j])) %= mod;
}
void solve() {
init();
if (x <= 100) {
int ans = 0;
rep (i , 0 , x) (ans += f[i]) %= mod;
printf("%d\n" , ans);
return;
}
For (i , 0 , 100) A.a[0][i] = f[i + 1] , (A.a[0][100] += f[i + 1]) %= mod;
For (i , 0 , 99 ) B.a[i + 1][i] = 1;
B.a[100][100] = 1;
For (i , 0 , 100) B.a[i][99] = B.a[i][100] = cnt[100 - i];
For (i , 0 , 101) T.a[i][i] = 1;
for (x -= 100;x;x >>= 1) {
if (x & 1) T = T * B;
B = B * B;
}
A = A * T;
printf("%d\n" , (A.a[0][100] + 1) % mod);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
#endif
input();
solve();
return 0;
}