zoukankan      html  css  js  c++  java
  • [CodeForces-55D]Beautiful Numbers

    题目大意:
      问区间[l,r]内有多少正整数能被其各个数位上的所有数字整除。

    思路:
      数位DP。
      能被所有数位整除相当于能被所有数位的LCM整除。
      而1..9的LCM为2520。
      f[i][j][k][flag]表示DP到第i位,当前构成的数字在%2520意义下为j,当前各个数位的LCM为k,flag表示当前数是否为边界。
      第三维的k显然不会完全用到,事实上只会有48个可能的值,因此可以离散化。
      枚举当前数位p,设边界数的当前数位为cur,则转移方程为:
      f[i-1][(j*10+p)%SUM][mult[k][p-1]][false]+=f[i][j][k][false];
      f[i-1][(j*10+p)%SUM][mult[k][p-1]][false]+=f[i][j][k][true];(p<cur)
      f[i-1][(j*10+p)%SUM][mult[k][p-1]][true]+=f[i][j][k][true];(p==cur)
      压一下内存,可以用滚动数组。
      然而交上去发现会在第11个点TLE。
      试了各种奇怪的方法,并没有什么用。
      还发现不开优化跑40s的数据,开了O1只需要跑3s。
      最后开性能分析,发现是在lcm的地方花了很多时间。
      于是先打表出所有的LCM,然后就过了。
      (然而51Nod上是10000组数据,不用记忆化搜索根本过不了)

     1 #include<cstdio>
     2 #include<algorithm>
     3 using std::__gcd;
     4 typedef unsigned long long qword;
     5 inline qword getint() {
     6     register char ch;
     7     while(!__builtin_isdigit(ch=getchar()));
     8     register qword x=ch^'0';
     9     while(__builtin_isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const int SUM=2520,LCM=48;
    13 const qword pow[]={1ull,10ull,100ull,1000ull,10000ull,100000ull,1000000ull,10000000ull,100000000ull,1000000000ull,10000000000ull,100000000000ull,1000000000000ull,10000000000000ull,100000000000000ull,1000000000000000ull,10000000000000000ull,100000000000000000ull,1000000000000000000ull,10000000000000000000ull};
    14 int id[SUM+1];
    15 const int mul[]={1,2,3,4,5,6,7,8,9,10,12,14,15,18,20,21,24,28,30,35,36,40,42,45,56,60,63,70,72,84,90,105,120,126,140,168,180,210,252,280,315,360,420,504,630,840,1260,2520};
    16 inline int lcm(const int &a,const int &b) {
    17     return a/__gcd(a,b)*b;
    18 }
    19 int mult[LCM][LCM];
    20 inline void init() {
    21     for(register int i=0;i<LCM;i++) {
    22         id[mul[i]]=i;
    23     }
    24     for(register int i=0;i<LCM;i++) {
    25         for(register int j=0;j<LCM;j++) {
    26             mult[i][j]=id[lcm(mul[i],mul[j])];
    27         }
    28     }
    29 }
    30 qword f[2][SUM][LCM][2];
    31 inline qword calc(const qword &n) {
    32     if(!n) return 1;
    33     const int len=__builtin_log10(n)+1;
    34     __builtin_memset(f[len&1],0,sizeof f[len&1]);
    35     f[len&1][0][0][true]=1;
    36     for(register int i=len;i;i--) {
    37         __builtin_memset(f[!(i&1)],0,sizeof f[!(i&1)]);
    38         const int cur=n%pow[i]/pow[i-1];
    39         for(register int j=0;j<SUM;j++) {
    40             for(register int k=0;k<LCM;k++) {
    41                 if(!f[i&1][j][k][true]&&!f[i&1][j][k][false]) continue;
    42                 f[!(i&1)][(((j<<2)+j)<<1)%SUM][k][false]+=f[i&1][j][k][false];
    43                 f[!(i&1)][(((j<<2)+j)<<1)%SUM][k][!cur]+=f[i&1][j][k][true];
    44                 for(register int p=1;p<10;p++) {
    45                     f[!(i&1)][((((j<<2)+j)<<1)+p)%SUM][mult[k][p-1]][false]+=f[i&1][j][k][false];
    46                     if(p<cur) f[!(i&1)][((((j<<2)+j)<<1)+p)%SUM][mult[k][p-1]][false]+=f[i&1][j][k][true];
    47                     if(p==cur) f[!(i&1)][((((j<<2)+j)<<1)+p)%SUM][mult[k][p-1]][true]+=f[i&1][j][k][true];
    48                 }
    49             }
    50         }
    51     }
    52     qword ret=0;
    53     for(register int j=0;j<SUM;j++) {
    54         for(register int k=0;k<LCM;k++) {
    55             if(!(j%mul[k])) ret+=f[0][j][k][true]+f[0][j][k][false];
    56         }
    57     }
    58     return ret;
    59 }
    60 int main() {
    61     init();
    62     for(register int T=getint();T;T--) {
    63         const qword l=getint(),r=getint();
    64         __builtin_printf("%I64u
    ",calc(r)-calc(l-1));
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    Discuz安装(centos+宝塔)
    宝塔面板安装
    Java中设置classpath、path、JAVA_HOME的作用
    【JDK和Open JDK】平常使用的JDK和Open JDK有什么区别
    提取Chrome插件为crx文件
    Python 01
    Java 01
    HTML5学习之FileReader接口
    formidable上传图片
    Mac系统下brew安装指定版本的nodejs小笔记
  • 原文地址:https://www.cnblogs.com/skylee03/p/7699195.html
Copyright © 2011-2022 走看看