zoukankan      html  css  js  c++  java
  • 洛谷 P1357 花园

    原题链接

    题解

    首先考虑$N leq 10^5$

    很容易想到动态规划

    我们不难设计状态

    $f_{i,j}$表示方案数

    $i$表示当前已经确定了$i$个位置

    $j$表示第$j-m+1~j$的二进制状态

    和状态转移方程

    $f_{i,j}=Sigma{f_{i-1,k}}(k,j都合法且k后接一位即为j)$

    故我们只需要预处理出所有状态是否合法和各个状态之间能否转换,然后动态规划即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int MOD=1e9+7,MAXN=1e5+50,MAXM=8,MAXP=70;
     5 inline void add(int &x,int y){
     6     x=(x+y)%MOD;
     7 }
     8 LL N;
     9 int M,K;
    10 bool bin[MAXM],leg[MAXP]/*״̬ÊÇ·ñºÏ·¨*/,tran[MAXP][MAXP]/*תÒÆÊÇ·ñºÏ·¨*/;
    11 inline void sign(){
    12     int cur=0,nxt=0,sum[MAXM]={0};
    13     for(int i=1;i<=M;i++)
    14         cur=cur<<1|bin[i];
    15     for(int i=2;i<=M+1;i++)
    16         nxt=nxt<<1|bin[i];
    17     for(int i=1;i<=M+1;i++)
    18         sum[i]=sum[i-1]+bin[i];
    19     if(sum[M]>K||sum[M+1]-sum[1]>K)
    20         return;
    21     leg[cur]=leg[nxt]=1;
    22     tran[cur][nxt]=1;
    23 }
    24 void dfs(int x){/*ö¾Ù²¢±ê¼ÇËùÓкϷ¨µÄ״̬*/
    25     if(x==M+2){
    26         sign();
    27         return;
    28     }
    29     bin[x]=0;
    30     dfs(x+1);
    31     bin[x]=1;
    32     dfs(x+1);
    33 }
    34 int f[MAXN][MAXP],maxp,ans;
    35 inline void dp(int S){/*Çó½â´ÓÌض¨×´Ì¬³ö·¢µÄ·½°¸Êý*/
    36     memset(f,0,sizeof(f));
    37     f[M][S]=1;
    38     for(int i=M+1;i<=M+N;i++)
    39         for(int j=0;j<maxp;j++)
    40             for(int k=0;k<maxp;k++)
    41                 if(tran[j][k])/*´æÔÚjµ½kµÄתÒÆ*/
    42                     add(f[i][j],f[i-1][k]);
    43     add(ans,f[N+M][S]);
    44 }
    45 int main(){
    46     scanf("%lld%d%d",&N,&M,&K);
    47     dfs(1);
    48     maxp=1<<M;
    49     for(int i=0;i<maxp;i++)
    50         if(leg[i])
    51             dp(i);
    52     printf("%d",ans);
    53     return 0;
    54 }
    View Code

    然后考虑$N leq 10^{15}$

    观察我们预处理出的邻接矩阵(各个状态之间能否转换的矩阵),可以发现这实际上是一个传递闭包问题(类似于Floyd),每一个状态都会按着这个矩阵操作N次

    故可以使用矩阵快速幂优化,代码就很简单了

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int MOD=1e9+7,MAXN=1e5+50,MAXM=8,MAXP=70;
     5 inline void add(LL &x,LL y){
     6     x=(x+y)%MOD;
     7 }
     8 LL N,maxp,ans,M,K;
     9 bool bin[MAXM],leg[MAXP];
    10 struct matrix{
    11     LL a[MAXP][MAXP];
    12     matrix (){
    13         memset(a,0,sizeof(a));
    14     }
    15     friend matrix operator*(matrix x,matrix y){
    16         matrix ret;
    17         for(int i=0;i<maxp;i++)
    18             for(int j=0;j<maxp;j++)
    19                 for(int k=0;k<maxp;k++)
    20                     add(ret.a[i][j],x.a[i][k]*y.a[k][j]);
    21         return ret;
    22     }
    23 }tran,a;
    24 inline void sign(){
    25     int cur=0,nxt=0,sum[MAXM]={0};
    26     for(int i=1;i<=M;i++)
    27         cur=cur<<1|bin[i];
    28     for(int i=2;i<=M+1;i++)
    29         nxt=nxt<<1|bin[i];
    30     for(int i=1;i<=M+1;i++)
    31         sum[i]=sum[i-1]+bin[i];
    32     if(sum[M]>K||sum[M+1]-sum[1]>K)
    33         return;
    34     leg[cur]=leg[nxt]=1;
    35     tran.a[cur][nxt]=1;
    36 }
    37 void dfs(int x){
    38     if(x==M+2){
    39         sign();
    40         return;
    41     }
    42     bin[x]=0;
    43     dfs(x+1);
    44     bin[x]=1;
    45     dfs(x+1);
    46 }
    47 inline matrix pow(matrix x,LL y){
    48     matrix ret=x;
    49     y--;
    50     while(y){
    51         if(y&1){
    52                 ret=ret*x;
    53         }
    54         x=x*x;
    55         y>>=1;
    56     }
    57     return ret;
    58 }
    59 int main(){
    60     scanf("%lld%lld%lld",&N,&M,&K);
    61     maxp=1<<M;
    62     dfs(1);
    63     a=pow(tran,N);
    64     for(int i=0;i<maxp;i++)
    65         if(leg[i])
    66             add(ans,a.a[i][i]);
    67     printf("%lld",ans);
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    【概念】指针
    【c++】随机数
    组装一台计算机
    模拟打印机
    实现手机的某些功能
    作业
    static 静态内部类
    java中编译报错 ClassCastException 是什么原因,如何处理
    作业1 2
    作业2
  • 原文地址:https://www.cnblogs.com/guoshaoyang/p/11139346.html
Copyright © 2011-2022 走看看