zoukankan      html  css  js  c++  java
  • [CodeChef-DGTCNT]Chef and Digits

    题目大意:
      若一个十进制数$x$(不含前导零)满足数码$i$恰好出现$t_i$次,则这个数是坏的,否则是好的。求区间$[L,R](1le L,Rle10^{18})$中有多少好数。

    思路:
      显然可以将区间$[L,R]$拆成$[1,R],[1,L)$分别计算。考虑计算区间$[1,n]$中好数的个数,可以用类似数位DP的方法,对于长度与$n$相等的情况枚举与$n$的LCP和LCP前的数字,否则枚举长度及首位数字直接计算。当限制不存在时,显然可以通过组合数计算答案。加上限制可以用容斥来计算,极限数据时间复杂度约$O(2^{10}cdot18cdot10cdot18)$。

     1 #include<cstdio>
     2 #include<cctype>
     3 typedef long long int64;
     4 inline int64 getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int64 x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 const int B=10,M=19;
    12 int t[B],tmp[B],dig[M],spc[B];
    13 int64 C[M][M],pow[B+1][M];
    14 inline int64 calc(int l) {
    15     int64 ret=1;
    16     for(register int i=1;i<=spc[0]&&l>=0;i++) {
    17         if(tmp[spc[i]]<0) return 0;
    18         ret*=C[l][tmp[spc[i]]];
    19         l-=tmp[spc[i]];
    20     }
    21     ret*=pow[10-spc[0]][l];
    22     return ret;
    23 }
    24 inline int64 count() {
    25     int64 ret=0;
    26     for(register int i=0;i<B;i++) tmp[i]=t[i];
    27     for(register int i=1;i<=dig[0]-1;i++) {
    28         for(register int j=1;j<B;j++) {
    29             tmp[j]--;
    30             ret+=calc(i-1);
    31             tmp[j]++;
    32         }
    33     }
    34     for(register int i=dig[0];i;i--) {
    35         for(register int j=i==dig[0];j<dig[i];j++) { 
    36             tmp[j]--;
    37             ret+=calc(i-1);
    38             tmp[j]++; 
    39         }
    40         tmp[dig[i]]--;
    41     }
    42     ret+=calc(0);
    43     return ret;
    44 }
    45 inline int64 solve(int64 n) {
    46     if(!n) return 0;
    47     for(dig[0]=0;n;n/=10) dig[++dig[0]]=n%10;
    48     int64 ret=0;
    49     for(register int i=0;i<1<<B;i++) {
    50         for(register int j=spc[0]=0;j<B;j++) {
    51             if((i>>j)&1) spc[++spc[0]]=j;
    52         }
    53         ret+=(__builtin_popcount(i)&1?-1:1)*count();
    54     }
    55     return ret;
    56 }
    57 inline void init() {
    58     for(register int i=0;i<M;i++) {
    59         for(register int j=C[i][0]=1;j<=i;j++) {
    60             C[i][j]=C[i-1][j-1]+C[i-1][j];
    61         }
    62     }
    63     for(register int i=0;i<=B;i++) {
    64         for(register int j=pow[i][0]=1;j<M;j++) {
    65             pow[i][j]=pow[i][j-1]*i;
    66         }
    67     }
    68 }
    69 int main() {
    70     init();
    71     for(register int T=getint();T;T--) {
    72         const int64 l=getint(),r=getint();
    73         for(register int i=0;i<B;i++) t[i]=getint();
    74         printf("%lld
    ",solve(r)-solve(l-1));
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    SQL Server中字段类型对应的C#中的数据类型
    ADO.NET复习总结(4)--访问SqlServer的类
    ADO.NET复习总结(3)--参数化SQL语句--防止sql注入式攻击
    关于MAX()函数的一点思考
    MySQL in or效率对比
    php trim源码分析
    MySQL MVCC机制
    一致性hash
    MySQL锁总结
    网关 php-cgi fastcgi phpfpm
  • 原文地址:https://www.cnblogs.com/skylee03/p/8877162.html
Copyright © 2011-2022 走看看