标签:数位dp bit limit set 个数 clu man 条件 discuss
【约束条件】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; }
标签:数位dp bit limit set 个数 clu man 条件 discuss
原文地址:https://www.cnblogs.com/w19567/p/11253733.html