線性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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章