Vasya has recently bought some land and decided to surround it with a wooden fence.
He went to a company called "Wooden board" that produces wooden boards for fences. Vasya read in the catalog of products that the company has at its disposal ndifferent types of wood. The company uses the i-th type of wood to produce a board of this type that is a rectangular ai by bi block.
Vasya decided to order boards in this company and build a fence from them. It turned out that the storehouse of the company is so large that Vasya can order arbitrary number of boards of every type. Note that Vasya is allowed to turn the boards as he builds the fence. However, Vasya cannot turn square boards.
Vasya is required to construct a fence of length l, however, an arbitrary fence won't do. Vasya wants his fence to look beautiful. We'll say that a fence is beautiful if and only if the following two conditions are fulfilled:
- there are no two successive boards of the same type
- the first board of the fence has an arbitrary length, and the length of each subsequent board equals the width of the previous one
In other words, the fence is considered beautiful, if the type of the i-th board in the fence is different from the i - 1-th board's type; besides, the i-th board's length is equal to the i - 1-th board's width (for all i, starting from 2).
Now Vasya wonders, how many variants of arranging a fence for his land exist. Your task is to count the number of different beautiful fences of length l.
Two fences will be considered the same if the corresponding sequences of fence boards types and rotations are the same, otherwise the fences are different. Since the sought number can be large enough, you need to calculate the answer modulo 1000000007 (109 + 7).
The first line contains two integers n and l (1 ≤ n ≤ 100, 1 ≤ l ≤ 3000) — the number of different board types and the fence length, correspondingly. Next n lines contain descriptions of board types: the i-th line contains two integers ai and bi(1 ≤ ai, bi ≤ 100) — the sizes of the board of the i-th type. All numbers on the lines are separated by spaces.
Print a single integer — the sought number of variants modulo 1000000007 (109 + 7).
2 3 1 2 2 3
2
1 2 2 2
1
6 6 2 1 3 2 2 5 3 3 5 1 2 1
20
In the first sample there are exactly two variants of arranging a beautiful fence of length 3:
- As the first fence board use the board of the first type of length 1 and width 2. As the second board use board of the second type of length 2 and width 3.
- Use one board of the second type after you turn it. That makes its length equal 3, and width — 2.
【题解】
大致题意:有一块地要围上篱笆,现在有m种篱笆,要求用这些篱笆围成长度为 l 的围墙,相邻两个篱笆不能是同一种,并且后一块篱笆的长度应为前一块篱笆的宽度,求最后能围成长为 l 的方案数。
分析:
很显然用动规做,但是怎么写递推式呢?
我们不妨分析一下,题中有两种状态,即取这块篱笆,和不取这块篱笆,似乎可以用状压做,但是再分析,一块篱笆还可以长宽互换,但是类型还是同一种类型,这一点在状压中就没办法表示,所以要放弃状压,那怎么办呢?题目说了,最后要求围成长度为 l 时的方案数,那长度为l 的方案数是不是就是长度为 l-1 时的方案数加上当前方案数,所以,
我们就可以用dp[i][j]表示当前长度为 i 时而最后一块篱笆为 j 类型时的方案数。
具体看代码注释。
【AC代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int inf=1e9+7;
typedef long long ll;
const int N=230;
const int M=3500;
int m,n;
int a[N],b[N];
ll dp[M][N];//表示长度为M且为第N种篱笆时的方案数
int main()
{
while(~scanf("%d%d",&m,&n))
{
memset(dp,0,sizeof(dp));
for(int i=0;i<m;++i)
{
scanf("%d%d",&a[i],&b[i]);
dp[a[i]][i]++; //类型为i长度为a[i]时的方案数加1
if(a[i]!=b[i])//如果不是正方形
{
a[i+m]=b[i];//长宽颠倒
b[i+m]=a[i];
dp[a[i+m]][i+m]++;//长宽互换后成为新的类型,方案数加1
}
}
for(int i=1;i<=n;++i)//遍历长度为i时的方案数
{
for(int j=0;j<m*2;++j)//遍历最后一个为j类型时的方案数
{
if(!dp[i][j]) continue;//不存在此种类型的篱笆
for(int k=0;k<2*m;++k)//寻找下一块长度等于当前宽度的篱笆
{
if(j%m!=k%m && a[k]==b[j])//前面是判断不为同一种类型 后面是判断下一块的长度等于上一块的宽度
dp[i+a[k]][k]=(dp[i+a[k]][k]+dp[i][j])%inf;//方案数累加
}
}
}
ll ans=0;
for(int i=0;i<2*m;++i)//统计长度为n最后一个类型为i时的方案数
ans=(ans+dp[n][i])%inf;
printf("%lld\n",ans);
}
return 0;
}