zoukankan      html  css  js  c++  java
  • [AHOI2009]同类分布

    题目大意:
      问在区间[l,r]内的正整数中,有多少数能被其个位数字之和整除。

    思路:
      数位DP。
      极端情况下,每一位都是9,所以各位数字之和不超过9*18。(为了方便这里用了9*19)
      f[i][j][k][flag],表示DP到从左往右第i位时,各位数字之和为j,这个数字在模mod意义下为k。
      flag表示是否为边界情况。
      转移的时候枚举这一位上的数p。
      设当前位是cur,则转移方程为:
      f[i-1][j+p][(k*10+p)%mod][false]+=f[i][j][k][false];
      f[i-1][j+p][(k*10+p)%mod][false]+=f[i][j][k][true];(p<cur)
      f[i-1][j+p][(k*10+p)%mod][true]+=f[i][j][k][true];(p=cur)
      观察发现f的第1维只会同时用到两层,所以可以滚动数组。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<cstring>
     4 typedef unsigned long long qword;
     5 inline qword getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register qword x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const qword pow[]={1ull,10ull,100ull,1000ull,10000ull,100000ull,1000000ull,10000000ull,100000000ull,1000000000ull,10000000000ull,100000000000ull,1000000000000ull,10000000000000ull,100000000000000ull,1000000000000000ull,10000000000000000ull,100000000000000000ull,1000000000000000000ull,10000000000000000000ull};
    13 const int SUM=9*19;
    14 qword f[2][SUM+1][SUM][2];
    15 inline qword calc(const qword &n) {
    16     const int len=__builtin_log10(n)+1;
    17     qword ret=0;
    18     for(register int mod=1;mod<=9*len;mod++) {
    19         memset(f[len&1],0,sizeof f[len&1]);
    20         f[len&1][0][0][true]=1;
    21         for(register int i=len;i;i--) {
    22             memset(f[!(i&1)],0,sizeof f[!(i&1)]);
    23             const int cur=n%pow[i]/pow[i-1];
    24             for(register int j=0;j<=mod;j++) {
    25                 for(register int k=0;k<mod;k++) {
    26                     for(register int p=0;p<10;p++) {
    27                         if(j+p>mod) break;
    28                         f[!(i&1)][j+p][((((k<<2)+k)<<1)+p)%mod][false]+=f[i&1][j][k][false];
    29                         if(p<cur) f[!(i&1)][j+p][((((k<<2)+k)<<1)+p)%mod][false]+=f[i&1][j][k][true];
    30                         if(p==cur) f[!(i&1)][j+p][((((k<<2)+k)<<1)+p)%mod][true]+=f[i&1][j][k][true];
    31                     }
    32                 }
    33             }
    34         }
    35         ret+=f[0][mod][0][false]+f[0][mod][0][true];
    36     }
    37     return ret;
    38 }
    39 int main() {
    40     const qword l=getint(),r=getint();
    41     printf("%llu
    ",calc(r)-calc(l-1));
    42     return 0;
    43 }
  • 相关阅读:
    hdu1865 1sting (递归+大数加法)
    hau1021 Fibonacci Again(递归)
    hdu2553 N皇后问题(dfs+回溯)
    BZOJ2342 [Shoi2011]双倍回文 【manacher】
    Manacher算法学习 【马拉车】
    BZOJ2743 [HEOI2012]采花 【离线 + 树状数组】
    BZOJ1296 [SCOI2009]粉刷匠 【dp】
    BZOJ1086 [SCOI2005]王室联邦 【dfs + 贪心】
    BZOJ1565 [NOI2009]植物大战僵尸 【最大权闭合子图 + tarjan缩点(或拓扑)】
    BZOJ2157 旅游 【树剖 或 LCT】
  • 原文地址:https://www.cnblogs.com/skylee03/p/7693076.html
Copyright © 2011-2022 走看看