P4127 [AHOI2009]同类分布

链接:https://www.luogu.org/problemnew/show/P4127

题目描述

给出两个数 a,ba,b ,求出 [a,b][a,b] 中各位数字之和能整除原数的数的个数。

输入输出格式

输入格式:

一行,两个整数 aa 和 bb

输出格式:

一个整数,表示答案

输入输出样例

输入样例#1: 复制

10 19

输出样例#1: 复制

3

说明

对于所有的数据, 1 ≤ a ≤ b ≤ 10^18

题解:数位dp, 但有一个问题,我们不知道各个数位数字之和;18*9是很小的,我们枚举一个一个试就可以了,这次学会了不用存顶上界,特判,情况少

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int digit[20];
ll dp[20][200][2][200];
ll dfs(int dep, int yu, int f, int t, int now, int sum){
    if(!dep) return !yu && sum == now;
    if(sum > now || sum + dep * 9 < now)return 0;
    if(dp[dep][yu][f][sum] != -1)return dp[dep][yu][f][sum];
    int i = f ? digit[dep] : 9;
    ll tmp = 0;
    for(; i >= 0; i--) {
        tmp += dfs(dep-1, (yu*10 + i) % now, f&(i == digit[dep]), i, now, sum+i);

    }
    return dp[dep][yu][f][sum] = tmp;
}

ll get(ll a){

    int cnt = 0;
    int now = 0;
    while(a){
        digit[++cnt] = a % 10;
        a /= 10;
        now += digit[cnt];
    }
    ll ans = 0;
    for(int i = 1; i <= 9*cnt; i++){
        memset(dp, -1, sizeof(dp));
        ans += dfs(cnt, 0, 1, 0, i, 0);
    }
    return ans;
}
// 1000000 7000000000000

int main(){
    int kk = clock();
    ll L, R;
    cin>>L>>R;
    ll ans1 = get(L-1);
    ll ans2 = get(R);
    cout<<ans2-ans1<<endl;
    int cc = clock();
    //cout<<cc-kk;
}

原文地址:https://www.cnblogs.com/EdSheeran/p/9397195.html

时间: 2024-11-04 01:15:00

P4127 [AHOI2009]同类分布的相关文章

[AHOI2009]同类分布

[AHOI2009]同类分布 求区间\([l,r]\)内的数,满足自己能整除自己各个数位上的和的数的个数,\(l,r\leq 10^{18}\). 解 不难得知设\(f_n\)为n以内的满足条件的数,答案即\(f_r-f_l\),因为递推中要表现整除,可以考虑摸递推. 要表现各个数位的和,又要变现长度,而且还要表现摸数,还有余数,故设\(f[i][j][k][l]\)表示i位的数,各数位的和为j,摸数为k,余数为l的数的方案数,因此不难有 \[f[i][j][k][l]=\sum_{p=0}^9

【数位DP】【P4127】[AHOI2009]同类分布

Description 给出两个数 \(a,~b\) 求出 \([a~,b]\) 中各位数字之和能整除原数的数的个数. Limitations \(1 \leq a,~b \leq 10^{18}\) Solution 考虑数位DP. 设数字 \(A = \sum_{i = 0}^k a_i \times 10^i\),其数字和 \(B = \sum_{i = 0}^k a_i\) 那么 \(A\) 满足条件即为 \(A \equiv 0 \pmod B\),根据同余的性质,可以将求和符号拆开:

【题解】AHOI2009同类分布

好开心呀~果然只有不看题解做出来的题目才会真正的有一种骄傲与满足吧ヾ(????)?" 实际上这题只要顺藤摸瓜就可以了.首先按照数位dp的套路,有两维想必是省不掉:1.当前dp到到的位数:2.0/1状态表示是否受限制(这一条是因为有数字上限).然后根据这两个维度来接着往下想.第二个维度先撇开不看,我们只考虑如何从第 \(i - 1\) 位dp到第 \(i\) 位.在这里其实卡了有点久,因为如果除数与被除数都在改变,那么两维的转移是非常凉凉的. 这个时候联想题目的特殊性质 ----- 当感觉无法优化

[luogu4127 AHOI2009] 同类分布 (数位dp)

传送门 Solution 裸数位dp,空间存不下只能枚举数字具体是什么 注意memset最好为-1,不要是0,有很多状态答案为0 Code //By Menteur_Hxy #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define Re registe

bzoj 1799: [Ahoi2009]self 同类分布 题解

[原题] 1799: [Ahoi2009]self 同类分布 Time Limit: 50 Sec  Memory Limit: 64 MB Submit: 554  Solved: 194 [Submit][Status] Description 给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数. Input Output Sample Input 10 19 Sample Output 3 HINT [约束条件]1 ≤ a ≤ b ≤ 10^18 Source Day1 [分析]

HYSBZ - 1799 self 同类分布

self 同类分布 HYSBZ - 1799 给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数.Sample Input 10 19 Sample Output 3 Hint [约束条件]1 ≤ a ≤ b ≤ 10^18 约束:一个数是它自己数位和的倍数,直接dp根本找不到状态,枚举数位和,因为总就162,然后问题就变成了一个数%mod=0,mod是枚举的,想想状态:dp[pos][sum][val],当前pos位上数位和是sum,val就是在算这个数%mod,(从高位算  *10

BZOJ1799 self 同类分布 数位dp

BZOJ1799self 同类分布 题意 给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数. [约束条件]1 ≤ a ≤ b ≤ 10^18 题解 1.所有的位数之和<9*18=1622.所以,dp[i][j][k][m]表示有i位(允许有前导0),数位和为k,模数为m,前i位与模数的模为j的符合条件的数的个数.这样要炸空间,怎么办!!其实这个dp的最后一维可以省去,因为对于不同的m值,dp互不相干.这样还是要超时的,有5亿多.于是就要卡常数,具体见代码里面的枚举的上下界. 代码 #

【BZOJ】1799: [Ahoi2009]self 同类分布

[题意]给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数.1 ≤ a ≤ b ≤ 10^18 [算法]数位DP [题解] 感觉这种方法很暴力啊. 枚举数位和1~162(不能枚举0,不然会模0,相当于除0),记忆化f[pos][sum][val],sum表示当前数位和,val表示数字取模枚举的数位和. 每次sum+i和(val*10+i)%MOD转移. sum用减法优化,即记忆化(MOD-sum),但是枚举过程中都要memset,导致效率低下,记忆化效果很差. 要什么方法才能跑1.3s

bzoj1799 [Ahoi2009]self 同类分布

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1799 [题解] 一眼看过去,数位dp! 想了想,发现数字和最多也就是$m = 9 \times 18 = 162$种,好像不是很大. 考虑枚举每种数字和$p$,做一遍dp. 设$f_{i,j,k}$表示到第$i$位,当前真实数字模$p$余$j$,当前所有数字的和为$k$的方案数.(不考虑前导0问题) 这个可以通过一个$O(18\times p^2 \times 10)$的动态规划解决. 接