一、题面
二、分析
关于这题,两个点。
第一个点,是需要能够分析出$[L,R]$区间的3的余数的个数。
首先,可以得到,$[L,R]$区间内共有$(R-L+1)$个数。
设定余数为0,1,2的为一组,那么1,2,0和2,0,1也是一组。那么可以肯定能得到$(R-L+1)/3$组。
那么还余下了$(R-L+1)%3$个数。这里就需要考虑从$L$开始往右移$(R-L+1)%3$个数,分析这几个数的余数即可。因为这几个数后的数肯定是能分成3个一组的。
第二个点,用DP的思维去求解。
区间内的数能分成0,1,2三种情况。那么如果有N位数,我们可以从第一位开始,不断的去往后组合。这样就得到了递推式。
求出最后DP[N][0]就是最终的结果。
三、AC代码
#include <bits/stdc++.h> using namespace std; const int MOD = 1e9+7; const int MAXN = 2e5; int N, L, R; long long DP[MAXN+3][3]; void solve() { memset(DP, 0, sizeof(DP)); int a, b, c; int temp = R-L+1; a = temp/3; b = temp/3; c = temp/3; temp%=3; for(int i = 0; i < temp; i++) { switch((L+i)%3) { case 0:a++;break; case 1:b++;break; case 2:c++;break; } } DP[0][0] = 1; for(int i = 1; i <= N; i++) { DP[i][0]= (DP[i-1][0]*a%MOD + DP[i-1][1]*c%MOD + DP[i-1][2]*b%MOD)%MOD; DP[i][1]= (DP[i-1][1]*a%MOD + DP[i-1][0]*b%MOD + DP[i-1][2]*c%MOD)%MOD; DP[i][2]= (DP[i-1][2]*a%MOD + DP[i-1][0]*c%MOD + DP[i-1][1]*b%MOD)%MOD; } printf("%I64d\n", DP[N][0]); } int main() { //freopen("input.txt", "r", stdin); scanf("%d %d %d", &N, &L, &R); solve(); return 0; }
原文地址:https://www.cnblogs.com/dybala21/p/10319282.html
时间: 2024-10-10 20:50:44