[AHOI2009]同类分布
作者:互联网
题目描述
给出两个数a,b,求出[a,b]中各位数字之和能整除原数的数的个数。
输入格式
一行,两个整数a和b
输出格式
一个整数,表示答案
输入输出样例
输入 #110 19输出 #1
3
说明/提示
对于所有的数据,1≤a≤b≤10181 ≤ a ≤ b ≤ 10^{18}1≤a≤b≤1018
【解题思路】
本题记录前面的数字的和,同时还要知道最后产生的数字是否整除和。
• 记录各位数字的和比较容易,共9*18个状态。关键是如何知道已经产生 的数位构成的数字是否整除最后的总和,比较麻烦。考虑求模,整除的 模数为0,可以记录已经产生的数字的模数,但是又不知道最后的数字总 和是多少,这个模数怎么记录?可以这样定义:
• F[20][200][200][200]->f[i][sum][m][mod]表示到第i位,前面数字总和为sum ,%mod的余数为m,然后枚举mod即可计算。
• 这样可以解决问题,但是计算内存发现:需要1G的内存,只好想办法压 缩空间,因为mod是要在程序中枚举的,所以不必记录这一维状态,这 样空间就足够了
• F[20][200][200]->f[i][sum][m]表示到第i位,前面数字总和为sum,%mod的 余数为m,然后枚举mod即可计算
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 long long dp[20][201][201],bit[21],a,b,MOD; 6 long long dfs(int p,int sum,int mod,int limt){//数位dp模板,被我改了点小地方 7 if(p==0){ 8 if(mod==0&&sum==MOD) 9 return 1; 10 else return 0;} 11 int up=limt?bit[p]:9; 12 if(!limt&&dp[p][sum][mod]!=-1)return dp[p][sum][mod]; 13 long long ret=0; 14 for(int i=0;i<=up;++i) 15 ret+=dfs(p-1,sum+i,(mod*10+i)%MOD,limt&&up==i); 16 if(!limt) 17 dp[p][sum][mod]=ret;return ret; 18 } 19 long long solve(long long n){ 20 int len=0,mod=0; 21 while(n){mod+=n%10; 22 bit[++len]=n%10;n/=10;} 23 long long ret=0; 24 for(MOD=1;MOD<=len*9;MOD++){//枚举 25 memset(dp,-1,sizeof(dp)); //这里必须清,当然,清成什么取决于你 26 ret+=dfs(len,0,0,1); 27 } 28 return ret; 29 } 30 int main(){ 31 scanf("%lld%lld",&a,&b); 32 printf("%lld",solve(b)-solve(a-1)); 33 return 0; 34 }
标签:200,数字,AHOI2009,sum,long,int,分布,同类,mod 来源: https://www.cnblogs.com/66dzb/p/11247164.html