• BZOJ 2734 集合选数


    高妙的算法—— 可以构造出形如:

    1  2  4   8   16  32 64

    3  6  12  24 48

    9  18 36 

    27 54

    的矩阵 相邻的数不能被同时选到 因此 将每一个数构造进矩阵 然后状态压缩dp 

    根据乘法原理 就可以 得出所有的方案

     1 #include <bits/stdc++.h>
     2 #define mod 1000000001
     3 using namespace std;
     4 int n,vis[100010],ans,num[23];
     5 int mps[20][20],tt[100000],x;
     6 int f[23][7000];
     7 bool check(int x)
     8 {
     9     for(int i=1;i<=18;i++)
    10         if((x>>(i-1))&(x>>i)) return 0;
    11     return 1;
    12 }
    13 void print(int x)
    14 {
    15     while(x) printf("%d",x&1),x/=2;
    16     printf("
    ");
    17 }
    18 void add(int &x,int y)
    19 {
    20     x+=y; if(x>=mod) x-=mod;
    21 }
    22 int solve()
    23 {
    24     for(int i=1;i<=tt[0]&&tt[i]<=(1<<num[1])-1;i++)
    25         f[1][i]=1;
    26     for(int i=2;i<=x;i++)
    27         for(int j=1;j<=tt[0]&&tt[j]<=(1<<num[i])-1;j++)
    28         {
    29             f[i][j]=0;
    30             for(int k=1;k<=tt[0]&&tt[k]<=(1<<num[i-1])-1;k++)
    31             if(!(tt[j]&tt[k])) add(f[i][j],f[i-1][k]);
    32         }
    33     int tmp=0;
    34     for(int i=1;i<=tt[0]&&tt[i]<=(1<<num[x])-1;i++)
    35         add(tmp,f[x][i]);
    36     long long gg=ans;
    37     gg*=tmp; gg%=mod;
    38     ans=gg;
    39 }
    40 int main()
    41 {
    42     scanf("%d",&n);ans=1;
    43     for(int i=0;i<(1<<18);i++)
    44         if(check(i)) tt[++tt[0]]=i;
    45     for(int i=1;i<=n;i++)
    46     {
    47         if(vis[i]) continue;mps[1][1]=i; x=1;
    48         vis[i]=1;num[1]=1;
    49         for(int j=2;mps[1][j-1]*2<=n;j++)
    50             vis[mps[1][j]=mps[1][j-1]*2]=1,num[1]=max(num[1],j);
    51         for(int j=2;mps[j-1][1]*3<=n;j++)
    52         {
    53             vis[mps[j][1]=mps[j-1][1]*3]=1;num[j]=1;
    54             for(int t=2;mps[j][t-1]*2<=n;t++)
    55                 vis[mps[j][t]=mps[j][t-1]*2]=1,num[j]=max(num[j],t);
    56             x++;
    57         }
    58     /*    for(int i=1;i<=x;i++)
    59         {
    60             for(int j=1;j<=num[i];j++)
    61                 printf("%d ",mps[i][j]);
    62             printf("
    ");
    63         }*/
    64         solve(); 
    65     }
    66     cout<<ans<<endl;
    67     return 0;
    68 }
  • 相关阅读:
    谁把天才变成了魔兽
    NetBeans 时事通讯(刊号 # 35 Nov 20, 2008)
    Java Annotation 手册
    《程序设计实践》读书笔记一
    5分钟让你明白金融危机爆发原因
    NetBeans 6.5 正式版可以下载了!
    Java Annotation 入门
    有关睡觉的学问
    oracle sql日期比较:
    C++编写安全OCX,IE不弹出安全提示
  • 原文地址:https://www.cnblogs.com/wcz112/p/6339841.html
Copyright © 2020-2023  润新知