这道题如果考虑从头到位枚举每一位每次只用考虑3*3种转移方式,于是题目重点就变成了如何找到L到R区间内%3后余数是1,2,3的数字各有多少个
我一开始是直接模拟的
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll now[3]; ll dp[200010][3]; const int MOD=1e9+7; int main() { int n,l,r; scanf("%d%d%d",&n,&l,&r); if(r-l+1<3&&r!=l) now[l%3]++,now[r%3]++; else if(r==l) now[l%3]++; else { int tmpl,tmpr; if(l%3==0) tmpl=l,now[0]++; else if(l%3==1) tmpl=l+2,now[1]++,now[0]++,now[2]++; else if(l%3==2) tmpl=l+1,now[2]++,now[0]++; if(r%3==0) tmpr=r; else if(r%3==1) tmpr=r-1,now[1]++; else if(r%3==2) tmpr=r-2,now[1]++,now[2]++; if(tmpl<tmpr) { for(int i=0;i<=2;i++) now[i]+=(tmpr-tmpl)/3; } } dp[1][0]=now[0]; dp[1][1]=now[1]; dp[1][2]=now[2]; for(int i=2;i<=n;i++) { for(int j=0;j<=2;j++) { for(int k=0;k<=2;k++) { dp[i][(j+k)%3]+=dp[i-1][j]*now[k]; dp[i][(j+k)%3]%=MOD; } } } printf("%lld\n",dp[n][0]); }
但是之后发现了个更好的方法,就是如果考虑余数为一的时候,把所有数字同一加上2;考虑余数为2的时候同一加上一,这样就相当于在新的区间内找有多少个可以整除3的数字
int c0 = (r/3 - (l-1)/3) % mod; int c1 = ((r+2)/3 - (l+1)/3)%mod; int c2 = ((r+1)/3 - (l)/3)%mod;
还可以解不等式来做比如说要找余数为一的数字 l≤3k+1≤r, l−1≤3k≤r−1,ceil( (l−1)/3 )≤k≤floor( (r−1)/3 ).