小九有一个长为 nnn 的整型数组,数组中的每个数都在 lll 和 rrr 之间,而且数组的和是 333 的整数倍。
请帮小九计算出这个数组一共有多少种不同的可能。
输出要对 109+710^9+7109+7 取模
数组的长度为 nnn,满足 1≤n≤1051 \le n \le 10^51≤n≤105。
数组中的每个元素都满足,l≤ai≤r,1≤l≤r≤109l \le a_i \le r, 1 \le l \le r \le 10^9l≤ai≤r,1≤l≤r≤109。
样例中,可能的数组有 [1,2],[2,1],[3,3][1,2], [2, 1], [3, 3][1,2],[2,1],[3,3]。
样例
输入:
n = 2
l = 1
r = 3
输出:
3
//
//重要信息:数组和是3的倍数,那么我们可以求出余数为0,1,2的组合数
//
//假设
//c0代表余数为0的组合数,c1代表余数为1的组合数,c2代表余数为2的组合数
//f0代表l - r余数为0的数量,f1代表l - r余数为1的数量,f2代表l - r余数为2的数量
//
//朴素的递推方式为:
//1:dp[i][c0] = dp[i - 1][c0] * f0 + dp[i - 1][c2] * f1 + dp[i - 1][c1] * f2
//2: dp[i][c1] = dp[i - 1][c1] * f0 + dp[i - 1][c0] * f1 + dp[i - 1][c2] * f2
//3 : dp[i][c2] = dp[i - 1][c2] * f0 + dp[i - 1][c1] * f1 + dp[i - 1][c0] * f2
//
//这里有个优化的小技巧,不用循环l - r的每个数字算f0, f1, f2,那样会超时,现在直接利用数量除以3算数量即可,详见代码
int restoreArray(int n, int l, int r) {
// write your code here.
int mod = 1000000000 + 7;
uint64_t f[3] = {0,0,0};
int v = l;
for (; v <= r && v % 3 != 1; v++)
{
f[v % 3]++;
}
int t = (r - v + 1) / 3;
int e = (r - v + 1) % 3;
f[0] += t;
f[1] += t;
f[2] += t;
if (e >= 1) {
f[1]++;
}
if (e > 1) {
f[2]++;
}
uint64_t c[3] ;
c[0] = f[0];
c[1] = f[1];
c[2] = f[2];
uint64_t t0;
uint64_t t1;
uint64_t t2;
for (int i = 1; i < n; i++)
{
t0 = c[0];
t1 = c[1];
t2 = c[2];
c[0] = (f[0] * t0 + f[1] * t2 + f[2] * t1) % mod;
c[1] = (f[0] * t1 + f[1] * t0 + f[2] * t2) % mod;
c[2] = (f[0] * t2 + f[1] * t1 + f[2] * t0) % mod;
}
return (int)c[0];
}