zoukankan      html  css  js  c++  java
  • codeforces 55d记忆化搜索

    题意:求l,r范围内能被自身所有非0digits整除的数的个数,范围是1~9e18

    题解:

             一个个digit判断很难搞,用lcm直接判断就会简单很多,如果所有种类的digit都有,那么1~9的lcm是2520,就算数少一点也必定是2520可以整除的数,那么根据这个进行状态转移。

             因为假设对于数字num判断是否符合条件只需要判断num是否可以整除一个小于等于2520的数就可以,所以转移的时候可以把num%2520进行记录,那么状态转移就只需要记录三个量,数字长度,到目前为止num的大小,到目前为止所有digit的lcm的大小在根据新加的digit转移就可以,可以直接记忆化搜索dfs(len,num,lcm,fg),fg用来判断此位数字是否有限制。

       开始对记忆化搜索理解不深一直在纠结应该怎样记录对于位数小于当前数的数的个数,其实记忆化搜索的时候根据fg完全可以直接记录下来,一点都不麻烦,具体看代码

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <iostream>
     5 #include <algorithm>
     6 #include <map>
     7 #include <vector>
     8 #include <queue>
     9 using namespace std;
    10 #define EPS 1e-10
    11 typedef long long ll;
    12 const int maxn = 1e5 + 10;
    13 const int INF = 1e9 ;
    14 const double eps = 1e-8;
    15 const int mod = 2520;
    16 int mp1[50],mp2[3000],dis[20];
    17 ll dp[20][2550][50];
    18 void init(){
    19     memset(dp,-1,sizeof(dp));
    20     int cnt = 0;
    21     for(int i = 1; i <= 2520;i++){
    22         if(2520 % i == 0){
    23             mp1[++cnt] = i;
    24             mp2[i] = cnt;
    25         }
    26     }
    27 }
    28 int gcd(int a,int b){
    29     return b == 0?a:gcd(b,a%b);
    30 }
    31 int getlcm(int u,int v){
    32     if(v == 0) return u;
    33     return u*v/gcd(u,v);
    34 }
    35 ll dfs(int len,int num,int lcm,int fg){
    36     if(len == 0) return num % mp1[lcm] == 0;
    37     if(!fg && -1 != dp[len][num][lcm]) return dp[len][num][lcm];
    38     int ed = fg?dis[len]:9;
    39     ll ans = 0;
    40     for(int i = 0;i <= ed;i++){
    41         int x = getlcm(mp1[lcm],i);
    42         ans += dfs(len - 1,(num*10+i) % mod,mp2[x],fg&&i==ed);
    43     }
    44     if(!fg) dp[len][num][lcm] = ans;//这里直接记录没有限制情况下的值提高效率
    45     return ans;
    46 }
    47 ll solve(ll u){
    48     int pos = 0;
    49     while(u > 0){
    50         dis[++pos] = u % 10;
    51         u /= 10;
    52     }
    53     return dfs(pos,0,1,1);
    54 }
    55 int main(){
    56    // freopen("in.txt","r",stdin);
    57     int T;
    58     cin>>T;
    59     init();
    60     while(T--){
    61         ll l,r;
    62         scanf("%I64d%I64d",&l,&r);
    63         printf("%I64d
    ",solve(r) - solve(l-1));
    64     }
    65     return 0;
    66 }
  • 相关阅读:
    盘符格式转换成NTFS格式
    jdk环境变量配置
    修改mysql密码
    端口占用解决
    程序执行原理
    第一个Python程序
    pip安装第三方库失败的问题
    windows本地安装mongoDB并且安装可视化工具studio 3t
    开发时前端测试方法
    虚拟机配置vimrc
  • 原文地址:https://www.cnblogs.com/shimu/p/5917587.html
Copyright © 2011-2022 走看看