这道题首先对于0个物品是一个常数项

此后每增加一个物品,dp[i]的最高次项便增加1

所以对于每一个dp值,最后都是可以用一个多项式表示的

考虑这个多项式什么时候构成一个循环

设所有物品的最小公倍数为lcm,则lcm就会形成一个循环

则dp函数的s也会在lcm时形成一个循环

因为lcm很小

那么我们可以考虑拉格朗日插值法来求出这个多项式

代码如下

#include<cstdio>
int l,r;
int dp[1000000],n,a[20],ans,lcm,maxa;
const int mod=1e9+7;
int fast(int x,int y)
{
	int ans=1;
	while(y)
	{
		if(y&1) ans=1ll*ans*x%mod;
		x=1ll*x*x%mod;
		y>>=1; 
	}
	return ans;
}
int moc(int x)
{
	if(x>=mod) return x-mod;
	if(x<0) return x+mod;
	return x;
}
int gcd(int x,int y)
{
	if(!y) return x;
	return gcd(y,x%y);
}
int solve(int x)
{
	int ans=0;
	int remain=x%lcm;
	for(int i=remain,j=1;j<=n+1;j++,i+=lcm)
	{
		int now=1;
		for(int k=remain,l=1;l<=n+1;l++,k+=lcm)
		if(j!=l)
		{
			now=1ll*now*moc(i-k)%mod;
		}
		now=fast(now,mod-2);
		for(int k=remain,l=1;l<=n+1;l++,k+=lcm)
		if(j!=l)
		{
			now=1ll*now*moc(x-k)%mod;
		}
		ans=moc(ans+1ll*dp[i]*now%mod);
	}//v=x,x[i]=i,y[i]=dp[i]
	return ans;
}
int main()
{
	freopen("gugu.in","r",stdin);
	freopen("gugu.out","w",stdout);
	scanf("%d",&n);
	lcm=1;
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]),lcm=a[i]/gcd(a[i],lcm)*lcm;
	scanf("%d%d",&l,&r);
	maxa=lcm*(n+1);
	dp[0]=1;
	for(int j=1;j<=n;j++)
	{
		for(int i=a[j];i<=maxa;i++)
		{
			dp[i]=moc(dp[i]+dp[i-a[j]]);
		}
	}
	for(int i=1;i<=maxa;i++)
	dp[i]=moc(dp[i]+dp[i-1]);
	printf("%d\n",moc(solve(r)-solve(l-1)));
}
/*
3 45 67 64
1 1000000000
*/