bzoj1799 luogu4127 同类分布
Posted w19567
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1799 luogu4127 同类分布相关的知识,希望对你有一定的参考价值。
1799: [Ahoi2009]self 同类分布
Time Limit: 50 Sec Memory Limit: 64 MBSubmit: 2455 Solved: 1124
[Submit][Status][Discuss]
Description
给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数。
Input
Output
Sample Input
10 19
Sample Output
3
HINT
【约束条件】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;
以上是关于bzoj1799 luogu4127 同类分布的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1799 [Ahoi2009] self 同类分布(数位DP)BZOJ千题计划(quexin
luogu P4127 [AHOI2009]同类分布 数位dp
luogu P4127 [AHOI2009]同类分布 数位dp
[luogu4127 AHOI2009] 同类分布 (数位dp)