1. 程式人生 > >洛谷P4127 [AHOI2009]同類分佈

洛谷P4127 [AHOI2009]同類分佈

數位$dp$

這裡我們首先考慮一種做法,就是記錄$f[pos][sum][num]$表示當前是第$pos$位,總的數字和為$sum$,現在的數字是$num$,那麼我們看看下面一行小字,輸入的數位數小於等於$1000$,????一臉懵逼,開個麼大的$f$陣列??於是我們優化一下,我們列舉模數就行了,具體看程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define N 21
using namespace std;
int val[N];
ll l,r,mod;
ll f[N][207][207];
ll Dfs(int pos,ll sum,ll num,bool limit,bool lead)
{
	if(!pos&!sum)
		return 0;
	if(!pos)
	{
		if(sum==mod&&!num)
			return 1;
		else
			return 0;	
	}
	
	if(!limit&&!lead&&f[pos][sum][num]!=-1)
		return f[pos][sum][num];
	int maxn=limit?val[pos]:9;
	ll ans=0;
	for(int i=0;i<=maxn;++i)
		ans+=Dfs(pos-1,sum+i,(num*10+i)%mod,limit&&(i==maxn),(lead&&!i));
	if(!limit&&!lead)
		f[pos][sum][num]=ans;
	return ans;
}
ll Get(ll x)
{
	int len=0;
	while(x)
	{
		val[++len]=x%10;
		x/=10;
	}
	ll ans=0;
	for(mod=1;mod<=9*len;++mod)
	{
		memset(f,-1,sizeof(f));
		ans+=Dfs(len,0,0,1,1);	
	}
	return ans;
}
int main()
{
	//memset(f,-1,sizeof(f));
	scanf("%lld%lld",&l,&r);
	printf("%lld",Get(r)-Get(l-1));
	return 0;
}