概述
题目链接:https://www.luogu.com.cn/problem/P4127
题目大意:
给出两个数a,b,求出[a,b]中各位数字之和能整除原数的数的个数。
题解:
各位数字之和最大为9*18=162,因此我们可以枚举数字之和。
定义状态为dp[pos][sum1][sum2]表示枚举到pos位,前面数位的和sum1,以及前面数位的组成的数对mod取余的结果。
最后判断一下sum1是否等于mod并且sum2对mod取余的结果为0.
trick:注意枚举mod的时候可以开一个全局的mod变量,然后再枚举,不能枚举i再把mod赋值为i,这样常数比较大。
上界为数位个数*9。
代码实现:
#pragma GCC optimize(2) #include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <cstdio> #include <cstdlib> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #define PI atan(1.0) * 4 #define E 2.718281828 #define rp(i, s, t) for (register int i = (s); i <= (t); i++) #define RP(i, t, s) for (register int i = (t); i >= (s); i--) #define ll long long #define ull unsigned long long #define mst(a, b) memset(a, b, sizeof(a)) #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 #define pii pair<int, int> #define mp make_pair #define pb push_back #define debug printf("acn"); using namespace std; inline int read() { int a = 0, b = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') b = -1; c = getchar(); } while (c >= '0' && c <= '9') { a = (a << 3) + (a << 1) + c - '0'; c = getchar(); } return a * b; } int a[20],num,mod; ll dp[20][200][200]; inline ll dfs(int pos,int sum1,int sum2,int limit){ if(pos==-1) return sum1==mod&&sum2==0; if(!limit&&dp[pos][sum1][sum2]!=-1) return dp[pos][sum1][sum2]; int up=limit?a[pos]:9; ll ans=0; rp(i,0,up) ans+=dfs(pos-1,sum1+i,(sum2*10+i)%mod,limit&&i==a[pos]); if(!limit) return dp[pos][sum1][sum2]=ans; return ans; } inline ll solve(ll x){ num=0; while(x) a[num++]=x%10,x/=10; ll res=0; for(mod=1;mod<=num*9;mod++){ mst(dp,-1); res+=dfs(num-1,0,0,1); } return res; } int main(){ ll l,r; scanf("%lld%lld",&l,&r); printf("%lldn",solve(r)-solve(l-1)); return 0; }
最后
以上就是留胡子野狼为你收集整理的luoguP4127——数位dp+枚举的全部内容,希望文章能够帮你解决luoguP4127——数位dp+枚举所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复