参考:https://www.cnblogs.com/fmj123/p/CF1105C.html
题意:
给个 n,l , r
从 l 到 r 里面挑n个数 组成的数组 和 是3的倍数。(可以重复利用某个数) 问,一共有几种方案
公式:(a+b)%3 => ( a%3+b%3)%3
想让 (a+b)%3==0 。 如果a%3 ==1 那就让 b%3 ==2 就行了,
a%3==2, 找b%3==1;
a%3==0 找b%3==0;
看规律来找
正整数 1 2 3 4 5 6 7 8 9
模完3以后 1 2 0 1 2 0 1 2 0
给定一个区间 (l , r ) 先(r-l)/3 大致 余数为 0,1,2 的(mod0,mod1,mod2) 都是三分之一,
然后根据上面的规律 确定下 mod0,mod1,mod2 具体值
然后开始dp
举个例子: dp[i][0]=(dp[i-1][0]*mod0 %mod + dp[i-1][1]*mod2 %mod + dp[i-1][2]*mod1 %mod ) %mod;
i个数,求和之后%3 的方案有多少种呢?
dp[i-1][0]*mod0 在 i-1 的基础上 在找个 %3=0 的数 就行了,,那这种数有几个呢? mod0 个 ;
dp[i-1][0] 和 mod0相乘是因为求方案数。
这里的 dp[i-1][0] 相当于一开始说的 (a+b)%3 中的a,
dp[i-1][1] 就找2 , dp[i-1][2] 就找1;
#include <bits/stdc++.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
const int mod=1000000007;
long long dp[200005][3];
int main(int argc, char** argv) {
int n;
long long l,r;
cin>>n>>l>>r;
long long mod0=(r-l+1)/3;
long long mod1=mod0;
long long mod2=mod0;
if(l%3==0)
{ if(r%3==0) mod0++;
if(r%3==1) mod0++,mod1++;
}
if(l%3==1)
{
if(r%3==1) mod1++;
if(r%3==2) mod1++,mod2++;
}
if(l%3==2)
{
if(r%3==0) mod0++,mod2++;
if(r%3==2) mod2++;
}
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
dp[i][0]=(dp[i-1][0]*mod0 %mod + dp[i-1][1]*mod2 %mod + dp[i-1][2]*mod1 %mod ) %mod;
dp[i][1]=(dp[i-1][0]*mod1 %mod + dp[i-1][1]*mod0 %mod + dp[i-1][2]*mod2 %mod ) %mod;
dp[i][2]=(dp[i-1][0]*mod2 %mod + dp[i-1][1]*mod1 %mod + dp[i-1][2]*mod0 %mod ) %mod;
}
cout<<dp[n][0]<<endl;
return 0;
}
找了几个题解 ,分析只有俩字母,DP。
你们倒是给我们解释一下啊;,就欺负小学生是吧。
https://www.cnblogs.com/fmj123/p/CF1105C.html 大哥在上,受小弟一拜。