Ayoub had an array a of integers of size n and this array had two interesting properties:
- All the integers in the array were between l and r (inclusive).
- The sum of all the elements was divisible by 3.
Unfortunately, Ayoub has lost his array, but he remembers the size of the array n and the numbers l and r, so he asked you to find the number of ways to restore the array.
Since the answer could be very large, print it modulo 109+7 (i.e. the remainder when dividing by 109+7). In case there are no satisfying arrays (Ayoub has a wrong memory), print 0.
Input
The first and only line contains three integers n, l and r (1≤n≤2⋅105,1≤l≤r≤109) — the size of the lost array and the range of numbers in the array.
Output
Print the remainder when dividing by 109+7 the number of ways to restore the array.
Examples
input |
---|
2 1 3 |
output |
3 |
input |
---|
3 2 2 |
output |
1 |
input |
---|
9 9 99 |
output |
711426616 |
Note
In the first example, the possible arrays are : [1,2],[2,1],[3,3].
In the second example, the only possible array is [2,2,2].
题目大意
求在数字a和b范围之间找出n个数(数字可以重复),其和能被3整除的方案数量。
解题思路
这道题要用到动态规划(声明一个二维数组dp[a][b]),一维变量来表示长度(即数量的个数),二维变量来表示对3取余的余数,在程序开头进行一个预处理,统计出余数分别为0,1,2的个数,但如果直接用循环的话会超时,这时候就用到除数计算R内的数量减去L内的数量来得到结果。
AC代码
#include <bits/stdc++.h>
#define INF 0x3f3f3f
#define Max_N 200000+5
using namespace std;
const int mod=1e9+7;
typedef long long ll;
typedef unsigned long long ull;
int dp[Max_N][4];
int main(int argc, char const *argv[])
{
int n,l,r;
cin>>n>>l>>r;
dp[0][0]=1;
int num[4];
memset(num,0,sizeof(num));
/*for(int i=l;i<=r;i++)
{
num[i%3]++;
}*///循环来统计数量的话会超时
num[0]=r/3+1;
if(r-1>=0)
num[1]=(r-1)/3+1;
if(r-2>=0)
num[2]=(r-2)/3+1;
if(l-1>=0)
num[0]-=max((l-1)/3+1,0);
if(l-2>=0)
num[1]-=max((l-2)/3+1,0);
if(l-3>=0)
num[2]-=max((l-3)/3+1,0);
for(int i=1;i<=n;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<3;k++)
{
dp[i][(j+k)%3]=dp[i][(j+k)%3]+((num[k]*(ll)dp[i-1][j])%mod);
dp[i][(j+k)%3]%=mod;
}
}
}
cout<<dp[n][0]<<endl;
return 0;
}
总结
动态规划是个好东西,嘻嘻嘻!