P4127 [AHOI2009]同类分布

P4127 [AHOI2009]同类分布

题解

好的,敲上数位DP  DFS板子

记录一下填的各位数字之和 sum ,然后记录一下原数 yuan

最后判断一下  yuan%sum==0 不就好啦???

 

突然意识到 dp 数组咋存???

dp[pos][sum][yuan]

pos , sum 都可以记录,但是 yuan ??? 1e18???

 

我们可以把yuan取模啊!

yuan%mod  ?

取模啥呢???如果固定一个取模数字,结果很有可能就不对了,那就枚举吧

看到原式 yuan%sum ?= 0

mod = 1~sum 好啦

yuan%mod = 0 并且 sum=mod 不就相当于 yuan%sum==0 么

 

所以 dp[pos][sum][yuan%mod] 

 

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<queue>

using namespace std;

typedef long long ll;

inline ll read()
{
    ll ans=0;
    char last=' ',ch=getchar();
    while(ch<'0'||ch>'9') last=ch,ch=getchar();
    while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
    if(last=='-') ans=-ans;
    return ans;
}

ll a,b;
ll c[20],len=0;
ll dp[20][200][200];
ll mod;

ll dfs(ll pos,ll sum,ll k,ll yuan,bool limit,bool qdl)
{
    if(pos<=0) return sum==mod&&k==0;
    if(!limit&&!qdl&&dp[pos][sum][k]!=-1) return dp[pos][sum][k];
    ll ans=0;
    ll up=limit?c[pos]:9;
    for(ll i=0;i<=up;i++)
      ans+=dfs(pos-1,sum+i,(yuan*10+i)%mod,yuan*10+i,limit&&(i==up),qdl&&(i==0));
    if(!limit&&!qdl) dp[pos][sum][k]=ans;
    return ans;
}

ll fun(ll x)
{
    memset(c,0,sizeof(c));len=0;
    while(x)
    {
        c[++len]=x%10;
        x/=10;
    }
    
    ll ans=0;
    for(mod=1;mod<=len*9;mod++)
    {
        memset(dp,-1,sizeof(dp));
        ans+=dfs(len,0,0,0,1,1);    
    }
    return ans;
}

int main()
{
    a=read();b=read();
    printf("%lld\n",fun(b)-fun(a-1));
    
    return 0;
}

 

posted @ 2019-09-09 17:17  晔子  阅读(185)  评论(0编辑  收藏  举报