package com.raylew.algorithm.ntoj;
import java.util.Scanner;
/*
小王是通中的学生,打算参加物理竞赛,于是计划在寒假里强化一下物理竞赛习题。
他从图书馆借了一套物理竞赛习题集。他决定在以后的n天里要做完上面的S道习题。
为了能够尽快完成任务,小王强迫自己第i天至少要做a[i]道题。
但是,小王在假期里还有其他事情(例如过春节),每天的题量不能太多,他估计了一下,第i天做的题不能超过b[i](b[i]>=a[i])道。
现在小王想知道,究竟能有多少种方案能够在n天里做完这S道物理竞赛习题呢?小王请你写个程序帮他算一算。
具体来说,一个方案就是每天做的题的数目的序列,假设第i天完成x[i]道题(x[i]当然满足a[i]<=i<=b[i],且x[1]+x[2]+......+x[n]=S)。
那么向量(x[1],x[2],...,x[n])就对应了一个方案。两个方案是指他们对应的向量不同。
一共n+1行,第一行是两个整数n和S,用空格分开,分别表示天数和题目数(1<=n<=20,1<=S<=1000);
接下来n行每行两个整数,之间用空格隔开,分别表示第i天对做题数量的限制a[i]和b[i](0<=a[i]<=b[i]<=S)。
一个整数,表示满足条件的方案数T。
样例输入
3 11
2 5
1 6
3 4
样例输出
8
*/
public class B0010_2 {
static int count;
static int[] high;
static int[] low;
static int[] max;
static int[] min;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int days = scan.nextInt();
int n = scan.nextInt();
high = new int[days + 1];
low = new int[days + 1];
max = new int[days + 1];
min = new int[days + 1];
for (int i = 1; i <= days; i++) {
low[i] = scan.nextInt();
high[i] = scan.nextInt();
}
for (int i = 1; i <= days; i++) {
max[i] = max[i - 1] + high[i]; // 前面i天至多完成
min[i] = min[i - 1] + low[i]; // 至少完成
}
f(days, n);
System.out.println(count);
}
public static void f(int days, int n) {
if (n > max[days] || n < min[days])// 剪枝
return;
if (days == 1) {// 如果程序运行到最后一层说明存在可行解,不需要回溯
count++;
return;
}
for (int i = low[days]; i <= high[days]; i++) {
if (i > n)// 剪枝
break;
f(days - 1, n - i);
}
}
}