• 【BZOJ】2734: [HNOI2012]集合选数


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2734


    考虑$N=4$的情况:

    egin{bmatrix}
    1&3 &X \
    2&X &X \
    4&X &X
    end{bmatrix}

    其实就是吧最小值丢在了矩阵中${(0,0)}$的位置上,对于矩阵中的任意位置令${f[i][j]=f[i][j-1]*3}$,${f[i][j]=f[i-1][j]*2}$。

    这样一来问题就转换为了:在一个矩阵中选取任意多的数字使得没有两个相邻的数字被同时选取的方案数。这个就是经典的轮廓线DP模型。

    但是我们注意到并不是一个矩阵就覆盖了所有的数字,所以我们需要记录哪些数字已经在矩阵中出现过了,从小到大枚举数字,对于还没有出现的数字再把它丢到${(0,0)}$的位置在构造一个矩阵并进行DP。利用乘法原理计算贡献,易证一个数字有且仅有在一个矩阵中出现,所以这样就可以打成补充不漏的效果。


     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<cstdlib>
     6 #include<cmath>
     7 #include<cstring>
     8 using namespace std;
     9 #define maxn 1001000
    10 #define llg long long 
    11 #define md 1000000001
    12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    13 llg n,m,N,ans,flag[maxn];
    14 llg val[110][110],f[2][(1<<12)];
    15 llg work(llg S)
    16 {
    17     memset(val,0,sizeof(val));
    18     n=m=0;
    19     flag[S]=1;
    20     llg x=S;
    21     val[0][0]=S;
    22     while (x*2<=N) {n++; val[n][0]=val[n-1][0]*2; flag[val[n][0]]=1; x*=2; }
    23     x=S;
    24     while (x*3<=N) {m++; val[0][m]=val[0][m-1]*3; flag[val[0][m]]=1; x*=3;}
    25     for (llg i=1;i<=n;i++)
    26         for (llg j=1;j<=m;j++)
    27         {
    28             if (val[i][j-1]*3>N) break;
    29             val[i][j]=val[i][j-1]*3;
    30             flag[val[i][j]]=1;
    31         }
    32     llg la=0,now;
    33     memset(f,0,sizeof(f));
    34     f[la][0]=1;
    35     for (llg i=0;i<=n;i++)
    36         for (llg j=0;j<=m;j++)
    37         {
    38             now=la^1;
    39             memset(f[now],0,sizeof(f[now]));
    40             for (llg zt=0;zt<=(1<<(m+1));zt++)
    41                 if (f[la][zt]!=0)
    42                 {
    43                     llg nzt=zt;
    44                     f[la][zt]%=md;
    45                     if (nzt&(1<<j)) nzt-=(1<<j);
    46                     f[now][nzt]+=f[la][zt];
    47                     if ((val[i][j]==0) || (zt&(1<<j))) continue;
    48                     if (j!=0)
    49                     {
    50                         if (zt&(1<<(j-1))) continue;
    51                     }
    52                     nzt=zt;
    53                     nzt|=(1<<j);
    54                     f[now][nzt]+=f[la][zt];
    55                 }
    56             la=now;
    57         }
    58     llg tot=0;
    59             for (llg i=0;i<=(1<<(m+1));i++) tot+=f[now][i];
    60     tot%=md;
    61     return tot;
    62 }
    63 
    64 int main()
    65 {
    66     yyj("a");
    67     cin>>N;
    68     ans=1;
    69     for (llg i=1;i<=N;i++)
    70         if (!flag[i])
    71         {
    72             ans*=work(i);
    73             ans%=md;
    74         }
    75     cout<<ans;
    76     return 0;
    77 }
    本文作者:xrdog 作者博客:http://www.cnblogs.com/Dragon-Light/ 转载请注明出处,侵权必究,保留最终解释权!
  • 相关阅读:
    VS 文件编码
    CSS中强大的EM 弹性布局
    编辑器【updating】
    下一代Jquery模板JsRender
    HTML 特殊符号编码对照表
    ASP.NET 文摘 [updating]
    Html5/Html CSS3/css 文摘 [updating]
    在Sublime Text 2中设置任意扩展名文件的默认语法
    Delphi笔记Indy10.5.5 IdTcpServer 与 IdTcpClient Demo 服务器端
    基于silverlight的工作流编辑器
  • 原文地址:https://www.cnblogs.com/Dragon-Light/p/6395335.html
Copyright © 2020-2023  润新知