• 集合选数


    这是题目

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

    找了十分钟没找出来。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     }  
  • 相关阅读:
    狄利克雷卷积
    洛谷P2044 [NOI2012]随机数生成器
    Miller Rabin算法详解
    BZOJ3667: Rabin-Miller算法
    洛谷P3383 【模板】线性筛素数(Miller_Rabin)
    洛谷P3806 【模板】点分治1
    BZOJ1468: Tree
    Android Camera调用过程分析
    安卓开发37:自定义的HorizontalScrollView类,使其pageScroll的时候焦点不选中
    Android抖动动画
  • 原文地址:https://www.cnblogs.com/fenghaoran/p/6517239.html
Copyright © 2020-2023  润新知