线性dp+数学思维 Codeforces Round #533 (Div. 2) C题 Ayoub and Lost Array

Ayoub and Lost Array

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.


题目大意:求数组个数,这个数组要求长度为n,数组里面的数大小在 [l,r] 区间,并且数组和可以整除3;

数学思维,没有想到很难做;

从可以整除3入手,可以先预处理出 [l,r] 区间里面所有数余0,余1,余2 的个数,那么可以定义状态转移方程为:

dp[i][j] 表示前 i 个数和余 j 的种类数;

(dp[i][0]=dp[i-1][0]*sum0+dp[i-1][1]*sum2+dp[i-1][2]*sum1)%=mod;
(dp[i][1]=dp[i-1][0]*sum1+dp[i-1][1]*sum0+dp[i-1][2]*sum2)%=mod;
(dp[i][2]=dp[i-1][0]*sum2+dp[i-1][1]*sum1+dp[i-1][2]*sum0)%=mod;

十分巧妙;

代码:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=200100;
const int M=2000100;
const LL mod=1e9+7;
int sum0,sum1,sum2;
LL dp[N][3];
int main(){
	int n,l,r;cin>>n>>l>>r;
	sum0=r/3-l/3;
	if(l%3==0) sum0++;
	sum1=(r+2)/3-(l+2)/3;
	if(l%3==1) sum1++;
	sum2=(r+1)/3-(l+1)/3;
	if(l%3==2) sum2++;
	dp[1][0]=sum0,dp[1][1]=sum1,dp[1][2]=sum2;
	for(int i=2;i<=n;i++){
		(dp[i][0]=dp[i-1][0]*sum0+dp[i-1][1]*sum2+dp[i-1][2]*sum1)%=mod;
		(dp[i][1]=dp[i-1][0]*sum1+dp[i-1][1]*sum0+dp[i-1][2]*sum2)%=mod;
		(dp[i][2]=dp[i-1][0]*sum2+dp[i-1][1]*sum1+dp[i-1][2]*sum0)%=mod;
	}
	cout<<dp[n][0]<<endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章