Luogu P4127 [AHOI2009]同类分布 题解

Describe

题目链接

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

Solution

数位dp。

$DFS(x,sum,dig,lim)$分别表示第$x$位,当前数位之和为$sum$,数字为$dig$,是否到达极限。

但是数据极大,$dig$会达到${10}^{18}$是不可能来记忆化的,所以考虑取模

那么模多少好呢?很明显如果模$sum$是最好的,最后只要判断下是否等于$0$即可。

那么暴力跑$9\times len$次数位$dp$,求的是$sum==i$时的数位$dp$结果,最后加起来就好了。

P.S.这里参考了讨论区神仙的优化:如果最后各个数位之和绝对到不了要求的话直接$return 0$。

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[21],m,mod,f[21][201][201][2];
inline int DFS(int x,int sum,int dig,int lim){
	if(sum+9*x<mod) return 0;//优化
	if(x==0) return sum==mod&&dig==0;
	if(~f[x][sum][dig][lim]) return f[x][sum][dig][lim];
	int Max=lim?a[x]:9,res=0;
	for(int i=0;i<=Max;i++) res+=DFS(x-1,sum+i,(dig*10+i)%mod,lim&&(i==Max));
	return f[x][sum][dig][lim]=res;
}
inline int solve(int n){
	m=0;
	while(n){
		a[++m]=n%10;
		n/=10;
	}
	int res=0;
	for(mod=1;mod<=m*9;mod++) memset(f,-1,sizeof(f)),res+=DFS(m,0,0,1);//暴力枚举模数
	return res;
}
int L,R;
signed main(){return scanf("%lld%lld",&L,&R),printf("%lld\n",solve(R)-solve(L-1)),0;}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇