zoukankan      html  css  js  c++  java
  • CodeForces 55D Beautiful numbers

    题意:对于一个数n,如果它能被它各个数位上的除了0的数字整除,则是good number。给定区间[a, b],问good number的数量。(a, b <= 9×10^18)

    解法:首先很容易想到数位dp。至于能被一些数整除的问题,就考虑如果一个数能被a和b整除,则能被lcm(a, b)(最小公倍数)整除,而1~9的lcm为2520。然后,由于思维定势,这样之后我顺理成章地想到了用状态压缩的方法表示数x是否含有1~9,这样就妥妥地超时了....其实,最小公倍数不会超过50个,直接记录就好。于是乎,只需要一个d[20][50][2520]的数组即可。

       由于我第一次做数位dp的时候,看别人的题解错误理解了d数组的含义(现在很多题解都不写文字说明,在代码里稍微注释一下....真的容易理解偏差),导致我一直以来写的非递归形式的数位dp都是效率比较低的.....而恰巧前面的几道题状态数都很少,所以就过了,而这道题如果用那种方法写出来极限数据大概要跑0.7+s,10组test就跪了......(用比较快的写法10组test最终跑出来为0.4+s)。

       我写的代码,定义的d[i][j][k]表示长度为i的数,它各数位的数字的最小公倍数为idx[j],除以2520的余数是k的数一共有多少个,而速度较快的写法定义的d[i][j][k]做数位dp时扫描到第i位时,前面数字的最小公倍数为idx[j],前面的数的余数为k时,要使最终形成的数满足题意,后面i位数总共有多少种可能。具体讲出来好像比较抽象,看代码把...我把错误代码贴出来贴在最后。

    Ps:由于每次进位都会*10,所以其实可以只用保存mod 252的余数即可,具体怎么写我把NotOnlySuccess的代码贴出来。

    PPs:虽然这道题浪费了很多时间....但是感觉对数位dp的理解更加到位了,也算是有所收获吧....

    tag:数位dp, good

    我的AC Code:

      1 /*
      2  * Author:  Plumrain
      3  * Created Time:  
      4  * File Name: DP-CF-55D-2.cpp
      5  */
      6 #include<iostream>
      7 #include<cstdio>
      8 #include<cstring>
      9 #include<string>
     10 #include<cmath>
     11 #include<algorithm>
     12 #include<vector>
     13 #include<cstdlib>
     14 #include<sstream>
     15 #include<fstream>
     16 #include<list>
     17 #include<deque>
     18 #include<queue>
     19 #include<stack>
     20 #include<map>
     21 #include<set>
     22 #include<bitset>
     23 #include<cctype>
     24 #include<ctime>
     25 #include<utility>
     26 
     27 using namespace std;
     28 
     29 #define CLR(x) memset(x, 0, sizeof(x))
     30 #define CLR1(x) memset(x, -1, sizeof(x))
     31 #define PB push_back
     32 #define SZ(v) ((int)(v).size())
     33 #define INF 999999999999
     34 #define zero(x) (((x)>0?(x):-(x))<eps)
     35 #define out(x) cout<<#x<<":"<<(x)<<endl
     36 #define tst(a) cout<<#a<<endl
     37 #define CINBEQUICKER std::ios::sync_with_stdio(false)
     38 
     39 const double eps = 1e-8;
     40 const double PI = atan(1.0)*4;
     41 const int maxint = 2147483647;
     42 const int mod = 2520;
     43 
     44 typedef vector<int> VI;
     45 typedef vector<string> VS;
     46 typedef vector<double> VD;
     47 typedef pair<int, int> pii;
     48 typedef long long int64;
     49 
     50 inline int Mymod (int a, int b) {int x=a%b; if(x<0) x+=b; return x;}
     51 
     52 int dit[20], idx[mod+5];
     53 int64 d[20][50][mod];
     54 
     55 inline int lcm(int a, int b)
     56 {
     57     if (!a || !b) return max(a, b);
     58     return a / __gcd(a, b) * b;
     59 }
     60 
     61 int64 rec(int p, int sum, int cnt)
     62 {
     63     if (p < 0) return sum % cnt == 0;
     64     
     65     int64& ret = d[p][idx[cnt]][sum];
     66     if (ret != -1) return ret;
     67     ret = 0;
     68     for (int i = 0; i < 10; ++ i)
     69         ret += rec (p-1, (sum*10+i)%mod, lcm(cnt, i));
     70     return ret;
     71 }
     72 
     73 int64 gao(int64 x)
     74 {
     75     if (x < 10) return x;
     76 
     77     int len = 0;
     78     while (x){
     79         dit[len++] = x % 10;
     80         x /= 10;
     81     }
     82 
     83     int sum = 0, cnt = 1;
     84     int64 ret = 0;
     85     for (int i = len-1; i >= 0; -- i){
     86         for (int t = 0; t < dit[i]; ++ t)
     87             ret += rec(i-1, (sum*10+t)%mod, lcm(cnt,t));
     88 
     89         cnt = lcm(cnt, dit[i]);
     90         sum = (sum*10 + dit[i]) % mod;
     91     }
     92     return ret;
     93 }
     94 
     95 void init()
     96 {
     97     CLR1 (d);
     98     int all = 0;
     99     for (int i = 1; i <= mod; ++ i)
    100         if (mod % i == 0) idx[i] = all++;
    101 }
    102 
    103 int main()
    104 {
    105 //    freopen("a.in","r",stdin);
    106 //    freopen("a.out","w",stdout);
    107 //    std::ios::sync_with_stdio(false);
    108     init();
    109     int T;
    110     scanf ("%d", &T);
    111     while (T--){
    112         int64 a, b;
    113         cin >> a >> b;
    114         cout << gao(b+1) - gao(a) << endl;
    115     }
    116     return 0;
    117 }
    View Code

    NotOnluySuccess:

    我的TLE代码(非递归):

      1 /*
      2  * Author:  Plumrain
      3  * Created Time:  2013-12-17 19:56
      4  * File Name: DP-CF-55D.cpp
      5  */
      6 #include <iostream>
      7 #include <cstdio>
      8 #include <cstring>
      9 #include <string>
     10 #include <cmath>
     11 #include <algorithm>
     12 #include <vector>
     13 #include <cstdlib>
     14 #include <sstream>
     15 #include <fstream>
     16 #include <list>
     17 #include <deque>
     18 #include <queue>
     19 #include <stack>
     20 #include <map>
     21 #include <set>
     22 #include <bitset>
     23 #include <cctype>
     24 #include <ctime>
     25 #include <utility>
     26 
     27 using namespace std;
     28 
     29 #define CLR(x) memset(x, 0, sizeof(x))
     30 #define CLR1(x) memset(x, -1, sizeof(x))
     31 #define PB push_back
     32 #define SZ(v) ((int)(v).size())
     33 #define ALL(t) t.begin(),t.end()
     34 #define INF 999999999999
     35 #define zero(x) (((x)>0?(x):-(x))<eps)
     36 #define out(x) cout<<#x<<":"<<(x)<<endl
     37 #define tst(a) cout<<#a<<endl
     38 #define CINBEQUICKER std::ios::sync_with_stdio(false)
     39 
     40 const double eps = 1e-8;
     41 const double PI = atan(1.0)*4;
     42 const int maxint = 2147483647;
     43 const int N = 1 << 10;
     44 const int mod = 2520;
     45 
     46 typedef vector<int> VI;
     47 typedef vector<string> VS;
     48 typedef vector<double> VD;
     49 typedef pair<int, int> pii;
     50 typedef long long Int64;
     51 
     52 inline int Mymod (int a, int b) {int x=a%b; if(x<0) x+=b; return x;}
     53 
     54 Int64 dit[30];
     55 Int64 ten[30], d[20][50][mod+5];
     56 int idx[50], num[mod+1], all;
     57 
     58 int lcm(int a, int b)
     59 {
     60     if ((!a) || (!b)) return max(a, b);
     61     return a / __gcd(a, b) * b;
     62 }
     63 
     64 void init()
     65 {
     66     ten[0] = 1;
     67     for (int i = 1; i < 19; ++ i)
     68         ten[i] = ten[i-1] * 10;
     69 
     70     CLR1 (num); CLR (idx);
     71     all = 0;
     72     for (int i = 1; i <= mod; ++ i) if (mod % i == 0){
     73         idx[all] = i; num[i] = all++;
     74     }
     75 
     76     CLR (d);
     77     d[1][0][0] = 1;
     78     for (int i = 1; i < 10; ++ i)
     79         d[1][num[i]][i] = 1;
     80 
     81     for (int i = 2; i < 19; ++ i){
     82         for (int j = 0; j < all; ++ j)
     83             for (int k = 0; k < mod; ++ k)
     84                 for (int t = 0; t < 10; ++ t){
     85                     int tmp = lcm(t, idx[j]);
     86                     d[i][num[tmp]][(k*10+t)%mod] += d[i-1][j][k];
     87                 }
     88     }
     89 }
     90 
     91 Int64 gao(Int64 x)
     92 {
     93     if (x < 10) return x+1;
     94 
     95     int len = 0;
     96     while (x){
     97         dit[len++] = x % 10;
     98         x /= 10;
     99     }
    100 
    101     int flag = 0, cnt = 0;
    102     Int64 ret = 0;
    103     for (int i = len-1; i; -- i){
    104         for (int j = 0; j < all; ++ j)
    105             for (int k = 0; k < mod; ++ k)
    106                 for (int t = 0; t < dit[i]; ++ t){
    107                     int tmp = lcm(t, lcm(flag, idx[j]));
    108                     if (((cnt + t*ten[i] + k) % tmp) == 0)
    109                         ret += d[i][j][k];
    110                 }
    111 
    112         flag = lcm(flag, dit[i]);
    113         cnt = (cnt + dit[i]*ten[i]) % mod;
    114     }
    115     for (int i = 0; i <= dit[0]; ++ i)
    116         if (((i+cnt) % lcm(flag, i)) == 0)
    117             ++ ret;
    118     return ret;
    119 }
    120 
    121 
    122 int main()
    123 {
    124     init();
    125     int T;
    126     scanf ("%d", &T);
    127     while (T--){
    128         Int64 a, b;
    129         cin >> a >> b;
    130         cout << gao(b) - gao(a-1) << endl;
    131     }
    132     return 0;
    133 }
    View Code
    ------------------------------------------------------------------
    现在的你,在干什么呢?
    你是不是还记得,你说你想成为岩哥那样的人。
  • 相关阅读:
    介绍Collection框架的结构;Collection 和 Collections的区别
    Mybites和hibernate的优缺点和区别2
    Mybites和hibernate的优缺点和区别
    AJAX如何获取从前台传递过来的数据然后在通过servle传递给后台
    list map set 集合的区别
    乐观锁和悲观锁的区别
    python生产消费Kafka
    python类型转换
    python实现远程方法调用
    Scala常用数据结构
  • 原文地址:https://www.cnblogs.com/plumrain/p/CF_55D.html
Copyright © 2011-2022 走看看