题意:
n个数的序列,这n个数的范围是[l,r],序列和是3的倍数,问满足题意的序列有多少种(%(1e9+7))。1<=n<=2e5 , 1 <= l , r <= 1e9。
题解:
1.统计[l,r]内模3为j的数目。
2.dp[i][j]表示前i个数模3为j的序列种类数。
3.状态转移方程:dp[i][(j + k) % 3] = (dp[i][(j + k) % 3] + dp[i - 1][j] * num[k]) % mod
4.初始化dp[1][j] = num[j]。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<vector>
#define N 200005
#define mod 1000000007
using namespace std ;
int n , l , r , temp1 , temp2 ;
int num[3] ;
long long dp[N][3] ;
int main()
{
int i , j , k ;
memset(num , 0 , sizeof(num)) ;
memset(dp , 0 , sizeof(dp)) ;
scanf("%d%d%d" , &n , &l , &r) ;
if(r - l <= 2)
{
for(i = l ; i <= r ; i ++)
num[i % 3] ++ ;
}
else
{
temp1 = l , temp2 = r ;
while(temp1 % 3 != 0)
temp1 -- ;
while(temp2 % 3 != 2)
temp2 ++ ;
for(i = 0 ; i < 3 ; i ++)
num[i] += (temp2 - temp1 + 1) / 3 ;
for(i = temp1 ; i < l ; i ++)
num[i % 3] -- ;
for(i = r + 1 ; i <= temp2 ; i ++)
num[i % 3] -- ;
}
for(i = 0 ; i < 3 ; i ++)
dp[1][i] = num[i] ;
for(i = 2 ; i <= n ; i ++)
for(j = 0 ; j < 3 ; j ++)
for(k = 0 ; k < 3 ; k ++)
dp[i][(j + k) % 3] = (dp[i][(j + k) % 3] + dp[i - 1][j] * num[k]) % mod ;
printf("%lld\n" , dp[n][0]) ;
}