cf 1105c 基础dp

题意:

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]) ;
}



 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值