【[AHOI2009]同类分布】
这是一篇有些赖皮的题解
(如果不赖皮的话,bzoj上也是能卡过去的)
首先由于我这个非常\(sb\)的方法复杂度高达\(O(171^4)\),所以面对极限的\(1e18\)的数据实在是卡死了
但是这个时候可以骗一下
一般来说肯定会有一个点的数据到达了\(1e18\),所以我们先将\(1\)到\(1e18\)之间的答案算出来,这样再去算另一个左边界的话至少可以节省一半的常数,就算左边界不是很小也有可能还算点希望
如果左边界特别小的话,可能就能幸运的卡过去
这道题的左边界就非常小啊,我估计不超过\(1e6\)
于是就卡过去了
再来看看我这个非常\(sb\)的dp,我觉得可能没有人这么写
我们设\(dp[i][j][s][k]\)表示一个数填到了\(i\)位,最高位填的是\(j\),数位和是\(s\),且这些数中对于某一个数取模得\(k\)的数的个数
至于这个某一个数是什么,我们当然是要最外面套上一个枚举数位和了
那么答案很简单啊,如果我们当前枚举的数位和是\(x\)的话,答案肯定就跟\(dp[][][x][0]\)有关系了
那么这个方程怎么转移呢
显然有
\]
\(t\)表示上一位填的数,\(i\)是位数,\(p\)是这一位填的数,\(j\)是数位和,\(k\)是对当前枚举的数位和取模之后的值,\(x\)表示当前枚举的数位和
同时我们发现好像直接去枚举\(t\)有些奢侈,我们可以直接把\(\sum_{t=0}^9dp[i][t][j][k]\)算好,于是我用\(dp[i][10][j][t]\)来存下来\(\sum_{t=0}^9dp[i][t][j][k]\),这样就可以优化转移了
之后就是数位\(dp\)的套路卡上界了,大概就是注意一下卡上界的时候存一下前面的数位和
复杂度大概是\(O((log_{10}n*9)^4)\),确实这是一个很垃圾的复杂度
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define maxn 172
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
LL dp[20][11][maxn][maxn];
LL L,R;
LL ans;
int num[2],a[20][2];
LL base[20];
LL mod;
inline LL qm(LL x) {return x>=mod?x-mod:x;}//优化一下取模
inline void spilt(LL x,int pd)
{
    num[pd]=0;
    while(x) a[++num[pd]][pd]=x%10,x/=10;
}//分解数位
inline void work(int x,int Len)
{
    mod=x;
    memset(dp,0,sizeof(dp));
    for(re int i=0;i<=9;++i)
        dp[1][i][i][qm(i)]+=1,dp[1][10][i][qm(i)]+=1;
    for(re int i=1;i<Len;++i)//枚举长度
        for(re int j=0;j<=min(x,i*9);++j)//枚举数位和
            for(re int k=0;k<x;++k)//枚举对当前枚举的数位和x取模后的值
                {
                    if(!dp[i][10][j][k]) continue;
                    for(re int p=0;p<=9;++p)
                        dp[i+1][p][j+p][(p*base[i]+k)%x]+=dp[i][10][j][k],dp[i+1][10][j+p][(p*base[i]+k)%x]+=dp[i][10][j][k];
                }
}
inline LL slove(int pd,int x)
{
    LL tot=0;
    for(re int i=1;i<num[pd];++i)
        tot+=dp[i][10][x][0]-dp[i][0][x][0];//统计所有位数小于给定数的,注意首位不能填0
    for(re int i=1;i<a[num[pd]][pd];++i)
        tot+=dp[num[pd]][i][x][0];//统计所有位数和给定数相同的,但是最高位小于给定数的
    LL now=a[num[pd]][pd],cnt=now;
    //now表示前面所有的数位和,cnt表示前面的数的值是多少
    //(比如说12345,卡到三这一位上,now=1+2=3,cnt=1*10+2*1=12)
    if(x-now<0) return tot;
    for(re int i=num[pd]-1;i;--i)//当前不同的那一位,[i+1,num]与x完全相同
    {
        LL t=qm(x-cnt*base[i]%x);//根据算出后面的数位所需要的余数是多少
        for(re int j=0;j<a[i][pd];j++)
            tot+=dp[i][j][x-now][t];
        //当前第i位可以填的数必须要小于给定数当前的这一位,这里就按照dp的方式来统计答案
        now+=a[i][pd];
        cnt=cnt*10+a[i][pd];
        cnt=qm(cnt);
        if(x-now<0) break;
    }
    return tot;
}
int main()
{
    scanf("%lld%lld",&L,&R);
    spilt(L,0),spilt(R+1,1);
    base[0]=1;
    for(re int i=1;i<=18;++i) base[i]=base[i-1]*10;
    if(R==1000000000000000000)
    {
    	ans+=29410615796612778;
    	for(re int i=1;i<=num[0]*9;++i)
        	work(i,num[0]),ans-=slove(0,i);
        printf("%lld\n",ans);
    	return 0;
	}//去掉这个if在bzoj上也能卡过去
    for(re int i=1;i<=num[1]*9;++i)//枚举数位和
        work(i,num[1]),ans+=slove(1,i)-slove(0,i);
    printf("%lld\n",ans);
    return 0;
}
												
											【[AHOI2009]同类分布】的更多相关文章
- 【BZOJ1799】[AHOI2009]同类分布(动态规划)
		
[BZOJ1799][AHOI2009]同类分布(动态规划) 题面 BZOJ 洛谷 题解 很容易想到数位\(dp\),然而数字和整除原数似乎不好记录.没关系,直接枚举数字和就好了,这样子就可以把整除原 ...
 - 洛谷  P4127 [AHOI2009]同类分布 解题报告
		
P4127 [AHOI2009]同类分布 题目描述 给出两个数\(a,b\),求出\([a,b]\)中各位数字之和能整除原数的数的个数. 说明 对于所有的数据,\(1 ≤ a ≤ b ≤ 10^{18 ...
 - P4127 [AHOI2009]同类分布
		
P4127 [AHOI2009]同类分布 题解 好的,敲上数位DP DFS板子 记录一下填的各位数字之和 sum ,然后记录一下原数 yuan 最后判断一下 yuan%sum==0 不就好啦??? ...
 - [BZOJ1799][AHOI2009]同类分布(数位DP)
		
1799: [Ahoi2009]self 同类分布 Time Limit: 50 Sec Memory Limit: 64 MBSubmit: 1635 Solved: 728[Submit][S ...
 - [AHOI2009]同类分布
		
题目大意: 问在区间[l,r]内的正整数中,有多少数能被其个位数字之和整除. 思路: 数位DP. 极端情况下,每一位都是9,所以各位数字之和不超过9*18.(为了方便这里用了9*19) f[i][j] ...
 - 【题解】AHOI2009同类分布
		
好开心呀~果然只有不看题解做出来的题目才会真正的有一种骄傲与满足吧ヾ(๑╹◡╹)ノ" 实际上这题只要顺藤摸瓜就可以了.首先按照数位dp的套路,有两维想必是省不掉:1.当前dp到到的位数:2. ...
 - [luogu4127 AHOI2009] 同类分布 (数位dp)
		
传送门 Solution 裸数位dp,空间存不下只能枚举数字具体是什么 注意memset最好为-1,不要是0,有很多状态答案为0 Code //By Menteur_Hxy #include < ...
 - 洛谷 P4127 [AHOI2009]同类分布
		
题意简述 求l~r之间各位数字之和能整除原数的数的个数. 题解思路 数位DP 代码 #include <cstdio> #include <cstring> typedef l ...
 - 【数位DP】【P4127】[AHOI2009]同类分布
		
Description 给出两个数 \(a,~b\) 求出 \([a~,b]\) 中各位数字之和能整除原数的数的个数. Limitations \(1 \leq a,~b \leq 10^{18}\) ...
 
随机推荐
- Jsp&Servlet入门级项目全程实录第1讲
			
惯例广告一发,对于初学真,真的很有用www.java1234.com,去试试吧! 1.jdbc数据库连接(略) 2.登录表单 2.1设置内边距 <dir style="padding- ...
 - 4 springboot 集成swagger2
			
Swagger:实时生成在线接口文档,方便测试和沟通 官网地址:https://swagger.io/ 引入依赖 <dependency> <groupId>io.spring ...
 - 学习Golang的步骤建议
			
一.快速入门 通过快速入门可以宏观的了解Go相关知识.快速入门可以去学习 go-tour 国内可以访问的中文版的 go-tour 地址有下面一些: http://gotour.qizhanming.c ...
 - code.google.com certificate error: certificate is for www.google.com
			
有时候我们会碰到下面错误:code.google.com certificate error: certificate is for www.google.com,类似如下: D:\>go ge ...
 - VS2012 常用配置
			
一. 整合svn版本控制 1. 点击此 下载与SVN版本相对应的ankhsvn插件,本人用的是Subversion 1.8 2. 安装ankhsvn插件,打开VS2012,右键任一工程,有显示如下图, ...
 - java设计模式-----9、观察者模式
			
Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态. Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对 ...
 - Dubbo(二)  一次惨痛的流血事故
			
时间定位到2018年11月某某一天,我正在看看Spring源码的文档,趁着没啥事,忽然想起Dubbo是基于Schema扩展的,所以就翻了下Dubbo的源码. 然后的然后,有活要干了,写完代码后,启动工 ...
 - Java 并发:Executor
			
异常捕获 以前使用executor的时候,为了记录任务线程的异常退出会使用ThreadFactory来设置线程的UncaughtExceptionHandler,但是按照书上的验证发现,采用execu ...
 - sublime_text3 快速生成xhtml表头手动设置
			
1. 在github上手动下载emmet安装插件 https://github.com/sergeche/emmet-sublime#how-to-install 2.把下载的安装插件放到packag ...
 - BZOJ3512:DZY Loves Math IV
			
传送门 Sol 好神仙的题目.. 一开始就直接莫比乌斯反演然后就 \(GG\) 了 orz 题解 permui 枚举 \(n\),就是求 \(\sum_{i=1}^{n}S(i,m)\) 其中\(S( ...