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 }
  • 相关阅读:
    SQL Server 2005 中的同义词
    SQL SERVER 2005中同义词实例
    聚集索引和非聚集索引(整理)
    linux kernel中timer的使用
    linux命令: patch
    win7(64位)php5.5-Apache2.4-mysql5.6环境安装
    tasklet和工作队列
    linux串口编程(c)
    Notepad++中Windows,Unix,Mac三种格式
    centos7/redhat7 将网卡名字改成eth样式的方法
  • 原文地址:https://www.cnblogs.com/skylee03/p/7693076.html
Copyright © 2011-2022 走看看