cf 1105 C. Ayoub and Lost Array(dp)

这道题如果考虑从头到位枚举每一位每次只用考虑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, l13kr1,ceil( (l−1)/3 )≤k≤floor( (r−1)/3 ).

猜你喜欢

转载自www.cnblogs.com/lishengkangshidatiancai/p/10298452.html