Codeforces Round #291 (Div. 2)E(DP+矩阵)

E. Darth Vader and Tree
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 modulo109 + 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.

Sample test(s)
input
3 3
1 2 3
output
8
题意:RT

思路:dp[i]表示距离根为不超过i的节点数量,因为节点与节点之间的边的范围为1-100,所以有dp[i]=dp[i-1]*cnt[1]+dp[i-2]*cnt[2]+......dp[i-100]*cnt[100]+1(自己),dp[]显然可以从1开始递推:
dp[0]=1;
dp[1]=dp[0]*cnt[1]+1;
dp[2]=dp[1]*cnt[1]+dp[0]*cnt[2]+1;
dp[3]=dp[2]*cnt[1]+dp[1]*cnt[2]+dp[0]*cnt[3]+1;
......
dp[x]=dp[x-1]*cnt[1]+dp[x-2]*cnt[2]+dp[x-3]*cnt[3]+......+dp[x-100]*cnt[100]+1;

那么不难想到可以构造矩阵A(1,101),矩阵B(101,101) (下标从1开始)

A:(1,0,0,0,...........,0,1)
B:(cnt[1],1,0,......,0,0)
       (cnt[2],0,1,......,0,0)
       (cnt[3],0,0,1,...,0,0)
         ......
    (cnt[98],0,0,.......,1,0)
    (cnt[99],0,0,.......,0,0)
  (cnt[100],0,0,.......,0,1)

 那么有A=A*B^(x)

因为初始:A其实为(dp[0],0,......,0,1)
           x=1   A为(dp[1],dp[0],0,......,0,1)
   x=2   A为(dp[2],dp[1],dp[0],......,0,1)
   ......
   x=x   A为(dp[x],dp[x-1],dp[x-2],......,0,1)

 最后A[1][1]就是答案

#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
         
         
using namespace std;

typedef long long ll;
const int MOD = (int)1e9+7;
const int MAXN = 102;
struct node{
    int a[MAXN][MAXN];
    int n,m;
    node(int N,int M){
        memset(a,0,sizeof(a));
        n=N;m=M;
    }
};

int add(int x,int y)
{
    x+=y;
    if(x>=MOD)x-=MOD;
    return x;
}

node operator * (const node&a,const node&b)
{
    node c(a.n,b.m);
    for(int i=1;i<=a.n;i++)
    for(int j=1;j<=b.m;j++){
        int res=0;
        for(int k=1;k<=a.m;k++)
            res = add(res , (ll)a.a[i][k]*b.a[k][j]%MOD);
        c.a[i][j]=res;
    }
    return c;
}
int main()
{
    int n,x;
    scanf("%d%d",&n,&x);
    node a(1,101),b(101,101);
    a.a[1][1]=a.a[1][101]=1;
    b.a[101][1]=b.a[101][101]=1;
    for(int i=2;i<=100;i++)
        b.a[i-1][i]=1;
    for(int i=0;i
         
         
           >=1; } printf("%d\n",a.a[1][1]); return 0; } 
         
        
        
       
       
      
      
     
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值