由于每个人只有两种重量50kg和100kg...并且人数只有至多50个...用dis[50][50][2]表示状态...dis[x][y][0]表示在原岸有x个50kg..y个100kg...dis[x][y][1]在目标岸有x个50kg..y个100kg...

    对于当前的一个状态...枚举多少个50kg..多少个100kg坐船去对岸(当然要船承受得了)....而对面的的状态可以推出来...

    如当前状态是 dis[x][y][0]...总人数中有50kg的人n1...有100kg的人n2...那么对岸的情况对应的是dis[n1-x][n2-y][1]...若是有a个50kg的和b个100kg的过河..那么对岸对应的状态是dis[n1-x+a][n2-y+b][1]...

    注意的是题目要求..每次过河的人至少一个..


Program:

#include<iostream>
#include<stack>
#include<queue>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<cmath>
#define ll long long
#define oo 1000000007
#define MAXN 55
using namespace std;
struct node
{
int n1,n2,tp;
}h,p;
ll dis[MAXN][MAXN][2],way[MAXN][MAXN][2],C[MAXN][MAXN];
queue<node> myqueue;
int n,k;
void PreWork()
{
int i,j;
for (i=0;i<=50;i++) C[i][0]=1;
for (i=1;i<=50;i++)
for (j=1;j<=50;j++)
C[i][j]=(C[i-1][j-1]+C[i-1][j])%oo;
return;
}
int main()
{
int i,j;
PreWork();
while (~scanf("%d%d",&n,&k))
{
int n1,n2;
n1=n2=0;
for (i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
if (x==50) n1++; else n2++;
}
memset(dis,0,sizeof(dis));
memset(way,0,sizeof(way));
dis[n1][n2][0]=1;
way[n1][n2][0]=1;
h.n1=n1,h.n2=n2,h.tp=0;
while (!myqueue.empty()) myqueue.pop();
myqueue.push(h);
while (!myqueue.empty())
{
h=myqueue.front();
myqueue.pop();
for (j=0;j<=h.n2;j++)
{
if (j*100>k) break;
for (i=0;i<=h.n1;i++)
{
if (!j && !i) continue;
if (i*50+j*100>k) break;
p.n1=n1-h.n1+i,p.n2=n2-h.n2+j,p.tp=1-h.tp;
if (!dis[p.n1][p.n2][p.tp])
{
myqueue.push(p);
dis[p.n1][p.n2][p.tp]=dis[h.n1][h.n2][h.tp]+1;
}
if (dis[p.n1][p.n2][p.tp]==dis[h.n1][h.n2][h.tp]+1)
{
ll t;
t=(C[h.n1][i]*C[h.n2][j])%oo;
t=(t*way[h.n1][h.n2][h.tp])%oo;
way[p.n1][p.n2][p.tp]=(way[p.n1][p.n2][p.tp]+t)%oo;
}
}
}
}
printf("%I64d\n%I64d\n",dis[n1][n2][1]-1,way[n1][n2][1]);
}
return 0;
}