BZOJ1799-[Ahoi2009]self 同类分布


题解:
我们统计前面的模数?
按照平常的思维,会定义 d p [ i ] [ j ] [ k ] 为当前扫到前i位,数位和为 j ,数字取模数位和后为 k ,跑一遍 R d p 再跑一遍 L 1 d p
然而跑一遍是不行的…因为前面的取模和后面的取模没有关系,之间是不能转移的….
那该如何思考?
所以这道题需要枚举数位和(也就是模数),对每个数位和都跑一次 d f s ,因为数字在 l o n g l o n g 范围内,数位和最大只会有 9 18 = 162 ,是可过的。
C o d e :

#include<bits/stdc++.h> 
#define ll long long
using namespace std;
ll f[21][200][200][2],a,b;
int n,sum=9*18+1,dight[20];
ll find(ll x,int mod)
{
    if(!x)return 0;
    memset(f,0,sizeof(f));
    int num=0;
    while(x)
    {
        dight[++num]=x%10;
        x/=10;
    }
    f[num+1][0][0][0]=1;
    for(int i=num+1;i>1;i--)
        for(int j=0;j<=mod;j++)
            for(int k=0;k<mod;k++)
            {
                if(!f[i][j][k][0]&&!f[i][j][k][1])continue;
                for(int p=0;p<=9;p++)
                {
                    if(p<dight[i-1]&&(j+p<=mod))f[i-1][j+p][(10*k+p)%mod][1]+=f[i][j][k][0];else
                        if(p==dight[i-1]&&(j+p<=mod))f[i-1][j+p][(10*k+p)%mod][0]+=f[i][j][k][0];
                    if(f[i][j][k][1]&&(j+p<=mod)) f[i-1][j+p][(10*k+p)%mod][1]+=f[i][j][k][1];
                }
            }
    return f[1][mod][0][0]+f[1][mod][0][1];
}
int main()
{
    scanf("%lld%lld",&a,&b);
    ll ans=0;
    for(int i=1;i<sum;i++)
        ans+=find(b,i)-find(a-1,i);
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_34531807/article/details/81146030
今日推荐