码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1799 luogu4127 同类分布

时间:2019-07-27 09:18:51      阅读:63      评论:0      收藏:0      [点我收藏+]

标签:数位dp   bit   limit   set   个数   clu   man   条件   discuss   

1799: [Ahoi2009]self 同类分布

Time Limit: 50 Sec  Memory Limit: 64 MB
Submit: 2455  Solved: 1124
[Submit][Status][Discuss]

Description

给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数。

Input

 

Output

 

Sample Input

10 19

Sample Output

3

HINT

【约束条件】1 ≤ a ≤ b ≤ 10^18

 

显然数位dp

一开始想的是设dp[pos][num][sum][mod][limit]表示满足各位数字之和为sum,原数模num为mod的pos位数的个数

然后空间复杂度20*200*200*200*2就爆掉了

然后发现其实对于第二维,每一次dfs的时候它都不会改变,一直传递下去

于是我们不妨省去这一维,每次改变num前将dp数组重新赋值为-1,再进行下一个num的dfs

转移方程:dp[pos][sum][mod][limit]=∑dp[pos][sum-i][(mod-i*10pos-1)%num][limit&(i==lim[pos])]

思路还是挺自然的......

 

#include<bits/stdc++.h>
using namespace std;
long long A,B;
int lim[20],cnt;
long long dp[20][200][200][2];
long long pow_10[20],ans;
long long dfs(int pos,int num,int sum,int ys,bool limit)
{
    if(sum<0) return 0;
    if(!pos && sum>0) return 0;
    if(dp[pos][sum][ys][limit]>-1) return dp[pos][sum][ys][limit];
    if(!pos) return 0;
    long long ret=0;
    int r=limit?lim[pos]:9;
    for(int i=0;i<=r;++i)
        ret+=dfs(pos-1,num,sum-i,((ys-pow_10[pos-1]*i)%num+num)%num,limit&(i==lim[pos]));
    dp[pos][sum][ys][limit]=ret;
    return ret;
}
void part(long long x,bool on)
{
    cnt=0;
    while(x)
    {
        lim[++cnt]=(x%10);
        x/=10;
    }
    for(int i=1;i<=cnt*9;++i)
    {
        memset(dp,-1,sizeof(dp));
        dp[0][0][0][0]=dp[0][0][0][1]=1;
        if(!on) ans+=dfs(cnt,i,i,0,1);
        else ans-=dfs(cnt,i,i,0,1);
    }
}
int main()
{
    pow_10[0]=1;
    for(int i=1;i<=18;++i) pow_10[i]=(pow_10[i-1]*10);
    scanf("%lld%lld",&A,&B);
    part(B,0); part(A-1,1);
    printf("%lld",ans);
    return 0;
}

 

 

bzoj1799 luogu4127 同类分布

标签:数位dp   bit   limit   set   个数   clu   man   条件   discuss   

原文地址:https://www.cnblogs.com/w19567/p/11253733.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!