• 【洛谷6400】[COI2008] UMNOZAK(数位DP水题)


    点此看题面

    • 定义一个数的自积为这个数乘上它的所有数码,求自积在([l,r])范围内的数的个数。
    • (Ale Ble10^{18})

    可能的数位积

    考虑某一位数码上最多只可能有(3)(2)(2)(3)(1)(2)(1)(3)(1)(5)(1)(7)

    因此我们可以直接枚举(2,3,5,7)各自的个数,求出至少需要多少位才可能存在这样一个数位积,那么至少需要位数超出(18)位的肯定直接不用管了。

    剩余的可能的数位积个数实际上并不多,实测只有(36100)个。

    数位(DP)

    首先是数位(DP)的经典差分,用([1,r])的答案减去([1,l-1])的答案,那么就相当于只要求解([1,n])形式的答案。

    直接枚举数位积(v_i),然后就是要求(lfloor1,lfloorfrac n{v_i} floor])范围内有多少个数的数位积是(v_i)

    先枚举从哪一位开始(因为可能有前导(0)),然后(DP)

    (f_{x,s,0/1})表示处理到第(x)位,剩余需要的数位积编号为(s),是否严格小于(n)的方案数。

    转移时枚举当前位填的数,首先不能超出这一位的限制,其次必须是(v_s)的因数。

    代码:(O()能过())

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define V 36100
    #define LL long long
    using namespace std;
    LL l,r,v[V+5],d[V+5];int tot;map<LL,int> id;
    int ct,a[20];I void Init(LL x) {ct=0;W(x) a[++ct]=x%10,x/=10;}
    LL f[20][V+5];I LL DP(CI x,CI s,CI fg=0)
    {
    	if(!x) return v[s]==1;if(d[s]>x) return 0;if(fg&&~f[x][s]) return f[x][s];//DP完;位数不够;记忆化
    	LL t=0;for(RI i=1,l=fg?9:a[x];i<=l;++i) !(v[s]%i)&&(t+=DP(x-1,id[v[s]/i],fg||(i^l)));//枚举当前位的数码
    	return fg&&(f[x][s]=t),t;//记忆化
    }
    I LL Calc(Con LL& n)
    {
    	LL t=0;for(RI i=1,j;i<=tot;++i) for(Init(n/v[i]),j=ct;j>=d[i];--j) t+=DP(j,i,j!=ct);return t;//枚举数位积,枚举最高位
    }
    int main()
    {
    	RI i,j,k,p,t;for(i=0;i<=3*18;++i) for(j=0;j<=2*18;++j) for(k=0;k<=18;++k) for(p=0;p<=18;++p)//枚举2,3,5,7个数
    		(t=i/3+(i%3>0)+j/2+(j%2>0)-(i%3==1&&j%2==1)+k+p)<=18&&(d[++tot]=t,id[v[tot]=(LL)pow(2,i)*pow(3,j)*pow(5,k)*pow(7,p)]=tot);//计算最少位数
    	return memset(f,-1,sizeof(f)),scanf("%lld%lld",&l,&r),printf("%lld
    ",Calc(r)-Calc(l-1)),0;//差分
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    IDEA 2017 安装和破解
    Linux新增开放端口
    ping指定IP的指定端口号
    Ubuntu防火墙常用命令
    Ubuntu端口常用命令
    File Zilla连接Ubuntu 失败
    Docker常用命令详解
    Linux的vi常用命令详解
    Qt事件系统之二:鼠标事件和滚轮事件
    Qt事件系统之一:Qt中的事件处理与传递
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu6400.html
Copyright © 2020-2023  润新知