• Little Elephant and Elections CodeForces


    Little Elephant and Elections CodeForces - 258B

    题意:给出m,在1-m中先找出一个数x,再在剩下数中找出6个不同的数y1,...,y6,使得y1到y6中数字4和7出现的总次数严格小于x中数字4和7出现的总次数。求方案数。

    方法:先数位dp分别预处理出:1到m之间,数字4和7出现的总次数为0到9的数。(总共最多10个数字,第一个最大1,因此4和7出现的总次数最多9次)然后枚举x,再暴力dfs枚举6个数,统计方案数。

    问题(细节):

    1.(13行)数位dp时,如果p<0则需要直接return0,否则导致数组越界WA。

    2.(55-61行)并非只需要枚举x,然后在出现4和7总次数小于x的数中任意取6个即可。要求不是6个数的最大值小于x,而是6个数的和小于x。

    3.(62-70行)逻辑错误,对比72-78行

    还可以写成

    1 for(i=1;i<=10;i++)
    2 {
    3     if(ans1[i]==0)    continue;
    4     nowmax=i;
    5     dfs(0,0,ans1[i]);
    6 }

    4.失败的dfs(不能按照从小到大的顺序取)

     1 void dfs(LL num,LL maxn,LL maxnum,LL sum,LL nowans)
     2 {
     3     if(sum>=nowmax)    return;
     4     if(num==6)
     5     {
     6         anss=(anss+nowans)%md;
     7         return;
     8     }
     9     if(maxnum+1<=ans1[maxn])
    10     {
    11         dfs(num+1,maxn,maxnum+1,sum+maxn,nowans*(ans1[maxn]-maxnum)%md);
    12     }
    13     LL i;
    14     for(i=maxn+1;i<nowmax;i++)
    15         if(ans1[i]>0)
    16         {
    17             dfs(num+1,i,1,sum+i,nowans*ans1[i]%md);
    18         }
    19 }

    程序:

     1 #include<cstdio>
     2 #include<cstring>
     3 #define md 1000000007
     4 typedef long long LL;
     5 LL ans[100][20][2];
     6 LL w[20];
     7 LL ans1[20];
     8 LL m,ttt,anss,low,anst;
     9 LL a[10];
    10 LL nowmax;
    11 LL dp(LL p,LL pos,bool pre0,bool limit)
    12 {
    13     if(p<0)    return 0;//曾经忘记,导致下面15行数组越界以及无用的dfs,导致WA
    14     if(pos<1)    return p==0&&!pre0;
    15     if(!limit&&ans[p][pos][pre0]!=-1)
    16         return ans[p][pos][pre0];
    17     LL i,res=0,end=limit?w[pos]:9;
    18     for(i=0;i<=end;i++)
    19         res+=dp(p-(i==4||i==7),pos-1,pre0&&i==0,limit&&i==w[pos]);
    20     return limit?res:(ans[p][pos][pre0]=res);
    21 }
    22 LL get(LL x,LL tt)
    23 {
    24     LL g;
    25     for(g=0;x>0;x/=10)    w[++g]=x%10;
    26     return dp(tt,g,1,1);
    27 }
    28 void dfs(LL num,LL sum,LL nowans)
    29 {
    30     if(sum>=nowmax)    return;
    31     if(num==6)
    32     {
    33         anss=(anss+nowans)%md;
    34         return;
    35     }
    36     LL i;
    37     for(i=0;i<nowmax;i++)
    38     {
    39         if(ans1[i]==0)    continue;
    40         ans1[i]--;
    41         dfs(num+1,sum+i,nowans*(ans1[i]+1)%md);
    42         ans1[i]++;
    43     }
    44 }
    45 int main()
    46 {
    47     LL i;
    48     memset(ans,-1,sizeof(ans));
    49     scanf("%I64d",&m);
    50     for(i=0;i<=10;i++)
    51     {
    52         //printf("%I64d  %I64d
    ",i,get(m,i));
    53         ans1[i]=get(m,i);
    54     }
    55 //    for(i=1;i<=10;i++)
    56 //    {
    57 //        low+=ans1[i-1];
    58 //        ttt=low*(low-1)%md*(low-2)%md*(low-3)%md*(low-4)%md*(low-5)%md;
    59 //        if(ttt<0)    ttt=0;
    60 //        anss=(anss+ttt*ans1[i])%md;//此版本错误
    61 //    }
    62 //    for(i=1;i<=10;i++)
    63 //    {
    64 //        if(ans1[i]==0)    continue;
    65 //        nowmax=i;
    66 //        //ans1[i]--;
    67 //        dfs(0,0,1);
    68 //        //ans1[i]++;
    69 //        anss=(anss*ans1[i])%md;//此版本错误
    70 //    }
    71     for(i=1;i<=10;i++)
    72     {
    73         if(ans1[i]==0)    continue;
    74         nowmax=i;
    75         anss=0;
    76         dfs(0,0,1);
    77         anst=(anst+anss*ans1[i])%md;
    78     }
    79     //printf("%I64d",anss);
    80     printf("%I64d",anst);
    81     return 0;
    82 }
  • 相关阅读:
    Linux配置java环境
    三级联动的实现
    Linux安装
    省市区县的sql语句——城市
    shiro登陆权限验证
    省市区县的sql语句——区县
    Linux安装Jenkins
    省市区县的sql语句——省
    读《世界是数字的》有感
    读《我是一只IT小小鸟》有感
  • 原文地址:https://www.cnblogs.com/hehe54321/p/cf-258b.html
Copyright © 2020-2023  润新知