zoukankan      html  css  js  c++  java
  • 集合选数

    这是题目

    大概就是让你找方案数嘛。开始我还以为是一道规律题,然后有愉快地打了一个暴搜打表。

    找了十分钟没找出来。www.oeis.org。结果... ...

    这是表

    半点规律没有。然后想了想DP,想不出线性或带log的。

    最后实在做不出来了,于是问了个大犇。大犇说这道题要用矩形。尼玛没在逗我。

    把题目意思转换一下嘛。就是有了X,就不能有2X和3X。

    然后依大犇所言构造一个介样的矩形:

    1 3 9 27
    2 6 18 54
    4 12 36 ...
    8 24 72 ...
    16 48 ... ...

    这样的话就构造出一个矩阵,满足 A[I][J]=2*A[I-1][J]=3*A[I][J-1];

    然后你就会发现,对于一个合法的方案,你选择了一个点,它的上下左右的点都不能选。

    然后想起炮兵阵地这道题,状压DP即可求出解(代码甚至更简单)。

    注意到这个矩阵内没有5,7,10... ... ,即以它们为左上角的点的方案没有算进去,于是开vis数组。因为各个矩阵内的数字互不影响(因为它们的基数不同),所以用乘法原理。

    代码什么的看看就好了,毕竟这题思维偏重。

     1     #include    <iostream>  
     2     #include    <cstdio>  
     3     #include    <cstdlib>  
     4     #include    <algorithm>  
     5     #include    <vector>  
     6     #include    <cstring>  
     7     #define LL long long int  
     8     #define ls (x << 1)  
     9     #define rs (x << 1 | 1)  
    10     #define fa (x >> 1)  
    11     #define MID int mid=(l+r)>>1  
    12     #define max(a,b) (a>b?a:b)  
    13     #define min(a,b) (a<b?a:b)  
    14     #define MOD 1000000001  
    15     using namespace std;  
    16     LL n,vis[101010],f[110][2049],a[21][21],Ans=1,line[40],tmp;  
    17     LL gi()  
    18     {  
    19         LL x=0,res=1;char ch=getchar();  
    20         while(ch!='-' && (ch>'9' || ch<'0'))ch=getchar();  
    21         if(ch=='-')res=-1,ch=getchar();  
    22         while(ch<='9'&&ch>='0')x=(x<<3)+(x<<1)+ch-48,ch=getchar();  
    23         return x*res;  
    24     }  
    25     LL calc(LL x)  
    26     {  
    27         a[1][1]=x;  
    28         for(int i=1;;++i)  
    29         {  
    30             if(i!=1)  
    31             {  
    32                 a[i][1]=a[i-1][1]*2;  
    33                 if(a[i][1]>n)  
    34                     {tmp=i-1;break;}  
    35             }  
    36             vis[a[i][1]]=1;  
    37             for(int j=2;;++j)  
    38             {  
    39                 a[i][j]=a[i][j-1]*3;  
    40                 if(a[i][j]>n)  
    41                     {line[i]=j-1;break;}  
    42                 vis[a[i][j]]=1;  
    43             }  
    44         }  
    45         line[0]=1;  
    46         for(int i=0;i<=tmp;++i)  
    47             for(int j=0;j<(1<<line[i]);++j)  
    48                 f[i][j]=0;  
    49         line[tmp+1]=0;f[tmp+1][0]=0;f[0][0]=1;  
    50         for(int i=0;i<=tmp;++i)  
    51         {  
    52             for(int j=0,k1=1<<line[i];j<k1;++j)  
    53             {  
    54                 if(f[i][j])  
    55                 {  
    56                     if(j & j>>1)continue;  
    57                     for(int k=0,k2=1<<line[i+1];k<k2;++k)  
    58                     {  
    59                         if(j&k)continue;  
    60                         f[i+1][k]=(f[i+1][k]+f[i][j])%MOD;  
    61                     }  
    62                 }  
    63             }  
    64         }  
    65         return f[tmp+1][0];  
    66     }  
    67     int main()  
    68     {  
    69         n=gi();  
    70         for(LL i=1;i<=n;++i)  
    71             if(!vis[i])  
    72                 Ans=(Ans*calc(i))%MOD;  
    73         cout<<Ans;  
    74     }  
  • 相关阅读:
    CF763C Timofey and Remoduling
    CF762E Radio Stations
    CF762D Maximum Path
    CF763B Timofey and Rectangles
    URAL1696 Salary for Robots
    uva10884 Persephone
    LA4273 Post Offices
    SCU3037 Painting the Balls
    poj3375 Network Connection
    Golang zip压缩文件读写操作
  • 原文地址:https://www.cnblogs.com/fenghaoran/p/6517239.html
Copyright © 2011-2022 走看看