zoukankan      html  css  js  c++  java
  • 【以前的空间】bzoj 1072 [SCOI2007]排列perm

      又颓废了一个下午,最近撸mc撸到丧失意识了,玩的有点恶心,于是找水题做,瞧不起颓废的自己啊。

      another水题。

      这题题意很明显啦,就是找数字排列后组成的数去mod d=0后有多少种。

      普通的搜索的话,是会tle的(应该是o(n!)没错?)。注意到长度n还是比较小的,于是想到状压dp。

      状态就是每个数取和不取组成的结果(就是00110表示第3,4个数取了啦,学过状压都知道)。

      然后转移就是f[i,j,k]表示现在取到第i个数状态为i余数为j有多少种情况,

      那么f[i,j,(k*10+a[i])mod d]=Σf[i-1,j',k](也就是同余的东西啦,在123后加一个数字4,那么1234 mod d=((123 mod d *10)+4 )mod d )。k的范围就是0-(d-1)啦。其实就是一个01背包,然后i是可以去掉的。

      最后就是处理重复的问题了,之前好像也做过类似的,不过反过来的……重复的话可以这么想,比如有4个2重复,那么对于第4个2来说,加上它后重复的情况就是之前的情况*4,对于第三个2来说,加上它后重复的情况就是之前的情况*3,对于第二个2就是之前的情况*2(其实就是个排列组合……四个2有序号要比没有序号多A(4,4)=4!)。

    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    var
      b:array[0..10,0..2000]of longint;
      c,a:array[0..20]of longint;
      f:array[0..2000,0..1500]of longint;
      i,j,k,l,n,m,t,tot,top:longint;
     
    procedure into;
    var
      i,j,k,len:longint;
      s:string;
    begin
      readln(s);
      len:=length(s);
      i:=pos(' ',s);
      val(copy(s,i+1,len-i),tot);
      delete(s,i,len-i+1);
      n:=length(s);
      fillchar(c,sizeof(c),0);
      for i:=1 to n do begin
        a[i]:=ord(s[i])-ord('0');
        inc(c[a[i]]);
      end;
      top:=1<<n-1;
      fillchar(b,sizeof(b),0);
      for i:=0 to top do begin
        j:=i;
        k:=0;
        while j<>0 do begin
          inc(k);
          dec(j,j and (-j));
        end;
        j:=k;
        inc(b[j,0]);
        b[j,b[j,0]]:=i;
      end;
    end;
     
    procedure work;
    var
      i,j,k,l,m,ans:longint;
    begin
      fillchar(f,sizeof(f),0);
      for i:=1 to n do
        f[1<<(i-1),a[i] mod tot]:=1;
      for i:=2 to n do
        for j:=1 to b[i,0] do begin
          k:=b[i,j];
          for l:=1 to n do
            if k and (1<<(l-1)) <> 0 then
              for m:=0 to tot-1 do
                inc(f[k,(10*m+a[l]) mod tot],f[k-1<<(l-1),m]);
        end;
      ans:=f[top,0];
      for i:=0 to 9 do
        if c[i]>1 then
          for j:=2 to c[i] do ans:=ans div j;
      writeln(ans);
    end;
     
    begin
      readln(t);
      while t>0 do begin
        dec(t);
        into;
        work;
      end;
    end.
    View Code
  • 相关阅读:
    datadog数据json格式转换prometheus文本格式
    clickhouse聚合
    iOS面试
    程序员如何快速准备面试中的算法
    李刚OC语言疯狂讲义笔记
    传智播客内部 学习网站+书籍分享
    iOS-多线程总结笔记
    iOS-简化单例模式(定义成宏 以后通用)
    iOS-单例模式(懒汉式和饿汉式)和GCD实现
    iOS-队列组
  • 原文地址:https://www.cnblogs.com/Macaulish/p/6492080.html
Copyright © 2011-2022 走看看