这是一篇有些赖皮的题解
(如果不赖皮的话,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]\)有关系了
那么这个方程怎么转移呢
显然有
\[dp[i+1][p][j+p][(p*10^i+k)\%x]=\sum_{t=0}^9dp[i][t][j][k]\]
\(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
#include
#include
#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