zoukankan      html  css  js  c++  java
  • 2020 hdu多校赛 第三场 1006 X Number

    题意:

    每次给你  L R d,问L~R中有多少个数 x 满足 x 各个位上的数 d 为唯一众数  ,如23323 中的 3,10000中的0,但是2233对于2和3都不算。(L<=1e18,R<=1e18,0<=d<=9)

    很显然,这是一个数位DP,按照数位DP的套路,我们需要计算从高到低前x-1位已经固定,第x位填y时,满足题意的数有多少。

    由于L,R只有1e18,我们不妨枚举d在剩下那几位中出现的次数,然后通过记忆化搜索 / 背包DP 求解。

    不过这只是整体思路。在枚举第一位为0时,我们还需要对于前导0特殊处理。总之细节很多,详情见代码。

      1 #include<iostream>
      2 #include<cstdlib>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cmath>
      7 #define N 25
      8 using namespace std;
      9 int T;
     10 long long L,R,d;
     11 int A[N],zz;
     12 int cnt[N],D[N];
     13 long long C[N][N];
     14 long long F[11][19][19];
     15 long long dfs(int x,int mx,int sm)
     16 {
     17     if(x==10)
     18     {
     19         if(sm==0)return 1;
     20         else return 0;
     21     }
     22     if(x==d) return dfs(x+1,mx,sm);
     23     if(F[x][mx][sm]!=-1)return F[x][mx][sm];
     24     long long ans=0;
     25     for(int i=0;i<=sm&&i+D[x]<mx;i++)
     26     {
     27         ans+=1ll*C[sm][i]*dfs(x+1,mx,sm-i);
     28     }
     29     return F[x][mx][sm]=ans;
     30 }
     31 long long work(long long x)
     32 {
     33     zz=0;
     34     x++;
     35     memset(cnt,0,sizeof(cnt));
     36     long long tmp=x;
     37     while(tmp)
     38     {
     39         zz++;
     40         A[zz]=tmp%10;
     41         tmp/=10;
     42     }
     43     for(int i=1;i<=zz/2;i++)
     44     {
     45         swap(A[i],A[zz-i+1]);
     46     }
     47     long long ans=0;
     48     memset(D,0,sizeof(D));
     49     for(int i=1;i<=zz;i++)
     50     {
     51         for(int j=0;j<A[i];j++)
     52         {
     53             if(i==1&&j==0)
     54             {
     55                 if(d!=0)
     56                 {
     57                     memset(F,-1,sizeof(F));
     58                     for(int k=1;k<zz;k++)
     59                     {
     60                         for(int l=1;l<=k;l++)
     61                         {
     62                             for(int o=0;o<l;o++)
     63                             {
     64                                 ans+=C[k-1][o]*C[k-o][l]*dfs(1,l,k-l-o);
     65                 
     66                             }
     67                         }
     68                     }
     69                 }
     70                 else
     71                 {
     72                     memset(F,-1,sizeof(F));
     73                     for(int k=1;k<zz;k++)
     74                     {
     75                         for(int l=1;l<k;l++)
     76                         {
     77                             ans+=C[k-1][l]*dfs(1,l,k-l);
     78                         }
     79                     }
     80                 }
     81                 continue;
     82             }
     83             cnt[j]++;
     84             D[j]++;
     85             int mx=0;
     86             for(int k=0;k<=9;k++)
     87             {
     88                 if(k==d) continue;
     89                 mx=max(mx,cnt[k]);
     90             }
     91             if(mx>=cnt[d])
     92             {
     93                 memset(F,-1,sizeof(F));
     94                 for(int k=mx-cnt[d]+1;k<=zz-i;k++)
     95                 {
     96                     ans+=C[zz-i][k]*dfs(0,k+cnt[d],zz-i-k);
     97                 }
     98             }
     99             else
    100             {
    101                 memset(F,-1,sizeof(F));
    102                 for(int k=0;k<=zz-i;k++)
    103                 {
    104                     ans+=C[zz-i][k]*dfs(0,k+cnt[d],zz-i-k);
    105                 //    if(x==239) cout<<i<<' '<<j<<' '<<k<<' '<<ans<<' '<<dfs(1,k+cnt[d],zz-i-k)<<endl;
    106                 }
    107             }
    108             cnt[j]--;
    109             D[j]--;
    110             
    111         }
    112         cnt[A[i]]++;
    113         D[A[i]]++;
    114     }
    115     return ans;
    116 }
    117 int main()
    118 {
    119 //    freopen("test.in","r",stdin);
    120 //    freopen("1.out","w",stdout);
    121     C[0][0]=1;
    122     for(int i=1;i<=19;i++)
    123     {
    124         C[i][0]=1;
    125         for(int j=1;j<=i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1];
    126     }
    127     scanf("%d",&T);
    128     while(T--)
    129     {
    130         scanf("%lld%lld%lld",&L,&R,&d); 
    131         printf("%lld
    ",work(R)-work(L-1));
    132     //    cout<<work(R)<<' '<<work(L-1)<<endl;
    133     }
    134     return 0;
    135 }
    136 /*
    137 1
    138 926 949 9
    139 
    140 
    141 3
    142 23123 243353 0
    143 23123 243353 5
    144 23123 243353 9
    145 
    146 2
    147 1 1000 0
    148 101 1000 0
    149 */
    View Code
  • 相关阅读:
    数据结构与算法参考答案(第十三周)
    数据结构与算法参考答案(第十二周)
    数据结构与算法参考答案(第十一周)
    数据结构与算法参考答案(第十周)
    数学建模国赛注意事项(持续更新)
    数值分析期末复习秘籍
    2020第十一届蓝桥杯软件类省赛第二场C/C++ 大学 B 组 填空题题解(未拿省一的个人反思)
    2020第十一届蓝桥杯软件类省赛第二场C/C++ 大学 B 组 E: 七段码(DFS,二进制枚举+并查集判重)
    递归实现指数型枚举(DFS)
    Codeforces Round #678 (Div. 2)B. Prime Square(矩阵均匀构造)
  • 原文地址:https://www.cnblogs.com/liutianrui/p/13395944.html
Copyright © 2011-2022 走看看