• Codeforces 55D


    题目链接:http://codeforces.com/problemset/problem/55/D

    题目大意:然你找出范围在[l,r]内,有多少个数满足可以被自身各个位上的数整除(0除外)。

    解题思路:最开始给出这样一个记录状态的方式,dp[pos][mod][lcm],即对应位置,当上一位时的数本身的值,到上一位为止各个位的最小公倍数。因为1~9的最大公约数为2520,所以pos[1,20],mod[1,10^18],lcm[1,2520],这样数组所需空间太大了。于是对mod做了处理,令mod=mod%2520,因为lcm最大为2520,所以这样不会影响最终的mod%lcm的结果。

        但这样还是不够,我们发现2520的因子只有48个(加上1和它本身),相信大家都知道一个数的因子的因子,也是这个数的因子,一直往下推....我们就知道最顶上的数的因子包含了它所有的因子的因子。那么我们就可以得出结论,如果当某一位lcm不是2520的因子的时候那它最后无论怎么跟别的数取公倍数都不会是2520的因子,所以大可以把这中lcm都归为一类进行记录。所以我们可以进行离散化,再开一个HASH[lcm]数组,基于48个因子对应的序号,剩下都归为一类当成0。

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 typedef long long ll;
     5 const int N = 25;
     6 const int LCM = 2520 + 5;//1~9的最小公倍数是2520 
     7 ll a[N];
     8 ll dp[N][LCM][50];
     9 ll HASH[LCM];//离散化
    10 
    11 ll gcd(ll a, ll b) {
    12     return b == 0 ? a : gcd(b, a%b);
    13 }
    14 
    15 ll dfs(ll pos, ll mod, ll lcm, bool limit) {
    16     if (pos == 0)  return mod%lcm == 0;
    17     if (!limit&&dp[pos][mod][HASH[lcm]] != -1)    return dp[pos][mod][HASH[lcm]];
    18     ll ans = 0;
    19     ll up = limit ? a[pos] : 9;
    20     for (int i = 0; i <= up; i++) {
    21         ans += dfs(pos - 1, (mod * 10 + i) % 2520, i==0?lcm:lcm/ gcd(lcm, i)*i, limit && (i == up));
    22     }
    23     if (!limit)    dp[pos][mod][HASH[lcm]] = ans;
    24     return ans;
    25 }
    26 
    27 ll solve(ll n) {
    28     ll top = 0;
    29     while (n) {
    30         a[++top] = n % 10;
    31         n /= 10;
    32     }
    33     return dfs(top, 0, 1, 1);
    34 }
    35 
    36 int main() {
    37     ios::sync_with_stdio(false);
    38     memset(dp, -1, sizeof(dp));
    39     int num = 1;
    40     for (int i = 1; i<= 2520; i++){
    41         if (2520 % i == 0){
    42             HASH[i] = num++;
    43         }
    44     }
    45     ll t;
    46     cin >> t;
    47     while (t--) {
    48         ll l, r;
    49         cin >> l >> r;
    50         ll ans = 0;
    51         ans += solve(r) - solve(l - 1);
    52         cout << ans << endl;
    53     }
    54 }
  • 相关阅读:
    js:语言精髓笔记1--标识符与基本类型
    ember.js:使用笔记4 数组数据的分组显示
    ember.js:使用笔记3 活用{{bind-attr}}
    ember.js:使用笔记2-数据删除与存储
    ember.js:使用笔记1-数组数据统一显示
    工具:使用jekyll生成静态网站
    css:删除:×的效果
    js写随机一个颜色
    回调函数的使用
    jquery获取select标签的选中元素
  • 原文地址:https://www.cnblogs.com/fu3638/p/6937831.html
Copyright © 2020-2023  润新知