Codeforces Round #533 (Div. 2) C. Ayoub and Lost Array(dp)

Description:

定义一种序列: 共有n个数 且都在 l 到 r 之间, 且他们的和能被3整除,问

给出n (1~2e5),l (1~1e9),r (1~1e9), 有多少种这样的序列。

Input:

n,l,r

Output:

answer mod 1e9+7

Analysis:

由于只考虑加和能被3整除,先将l到r之间的所有数,分成3类并计数,即3k+0,3k+1,3k+2. 然后就可以dp了,设dp[i][j]为i个数组成的序列,各元素加和能被3整除余下j的个数,状态转移不难写为

dp[i][(j + k) % 3] += dp[i-1][j] * a[k]  for k=0,1,2; 其中a[i]是指分为3k+i的数的个数

初始条件为 dp[0][0]=1

#include<iostream>
#define _CRT_SECURE_NO_WARNINGS
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<sstream>
#include<cmath>
#include<iterator>
#include<bitset>
#include<stdio.h>
#include<unordered_set>
#include<ctime>
#include<float.h>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;
const int INF = 1 << 30;
const int MOD = 1000000007;
const int maxn = 200005;

int dp[maxn][3],n,l,r;
int a[3];
int main() {
	while (cin >> n >> l >> r) {
		a[0] = r / 3 - (l - 1) / 3;
		a[1] = (r + 1) / 3 - l / 3;
		a[2] = (r + 2) / 3 - (l + 1) / 3;

		dp[0][0] = 1; dp[0][1] = 0; dp[0][2] = 0;

		_rep(i,1,n)
			_for(j, 0, 3)
				_for(k,0,3){
			dp[i][(j + k) % 3] = (dp[i][(j + k) % 3] + 1ll * dp[i-1][j] * a[k]%MOD) % MOD;
		}
		cout << dp[n][0] << endl;
	}


	return 0;
}

猜你喜欢

转载自blog.csdn.net/tomandjake_/article/details/86625364