zoukankan      html  css  js  c++  java
  • 【洛谷1357】花园

    原题:

     n<=1e15

    首先要看清题,花圃是环形的而不是线形的

    但是不妨先思考如果是线形该如何处理

    如果n<=1e5做法很显然,f[i][j]表示直到第i个点状态为j的方案数,其中j是二进制压状态

    然后可以发现转移都是f[i][j]+=f[i-1][k]的形式

    自然想到矩阵乘方法

    在转移矩阵A中,如果存在状态k能转移到状态j,那么a[k][j]为1否则为0

    设矩阵乘的格式为AB=C,A是m阶转移方阵,B和C是m阶列向量

    这样右侧列向量中b[j][1]就会乘上a[k][j](等于1),然后被加到c[k][1]上

    如果a[k][j]为0则b[j][1]就不会被转移到c[k][1]上,等价于f[i-1][j]不会转移到f[i][k]

    虽然矩阵乘没有交换律,但是只要每次把转移矩阵乘在最左边即可

    即AB=C变成AAB=A^2B=AC,这样就能转移任意次

    最后考虑怎么把线形情况扩展到环形情况

    首先可以快速幂出n-m次转移的转移矩阵,然后枚举前m个物品

    然后对每个枚举到的状态t,先令列向量b[t][1]=1,然后乘上转移矩阵得到答案向量C

    从C向量里挑出不会和状态t冲突的后m个物品的状态,累计答案

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 #define LL long long
     5 const int mo=1000000007;
     6 int m,o;  LL n;
     7 struct mtx{
     8     LL a[32][32];
     9     mtx(){
    10         for(int i=0;i<32;++i)for(int j=0;j<32;++j)
    11             a[i][j]=0;
    12     }
    13     mtx(int x){
    14         for(int i=0;i<32;++i)for(int j=0;j<32;++j)
    15             a[i][j]=0;
    16         for(int i=0;i<32;++i)
    17             a[i][i]=1;
    18     }
    19     mtx operator*(mtx y){
    20         mtx z;
    21         for(int i=0;i<32;++i)for(int j=0;j<32;++j)
    22             for(int k=0;k<32;++k)
    23                 z.a[i][j]=(z.a[i][j]+a[i][k]*y.a[k][j])%mo;
    24         return z;
    25     }
    26     void ot(){
    27         for(int i=0;i<(1<<m);++i){
    28             for(int j=0;j<(1<<m);++j)
    29                 printf("%lld ",a[i][j]);
    30             printf("
    ");
    31         }
    32         cout<<endl;
    33     }
    34 }a;
    35 mtx qcp(mtx x,LL y){
    36     mtx z=x,bwl(1);
    37     for(;y;y>>=1){
    38         if(y&1)  bwl=z*bwl;
    39         z=z*z;
    40     }
    41     return bwl;
    42 }
    43 bool chck(int x){
    44     int bwl=0;
    45     for(;x;x>>=1)  bwl+=(x&1);
    46     return bwl<=o;
    47 }
    48 bool chck2(int x,int y){
    49     for(;x;x>>=1){
    50         y>>=1;
    51         if(x&1)  y|=(1<<(m-1));
    52         if(!chck(y))  return false;
    53     }
    54     return true;
    55 }
    56 int main(){
    57     cin>>n>>m>>o;
    58     for(int i=0;i<(1<<m);++i)if(chck(i)){
    59         a.a[i>>1][i]=1;
    60         if(chck(i>>1|(1<<(m-1))))
    61             a.a[i>>1|(1<<(m-1))][i]=1;
    62     }
    63     mtx tmp=qcp(a,n-m);
    64     LL bwl=0;
    65     for(int i=0;i<(1<<m);++i)if(chck(i)){
    66         mtx ans;
    67         ans.a[i][0]=1;
    68         ans=tmp*ans;
    69         for(int j=0;j<(1<<m);++j)if(chck2(i,j))
    70             bwl=(bwl+ans.a[j][0])%mo;
    71     }
    72     cout<<bwl;
    73     /*
    74     mtx tmp=qcp(a,n-1);
    75     mtx ans;
    76     ans.a[0][0]=1,ans.a[1<<(m-1)][0]=1;
    77     ans=tmp*ans;
    78     LL bwl=0;
    79     for(int i=0;i<(1<<m);++i)  bwl=(bwl+ans.a[i][0])%mo;
    80     cout<<bwl<<endl;
    81     */
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    django实现github第三方本地登录
    django扩展User模型(model),profile
    WSGI
    Linux查看配置文件中未被注释的有效配置行
    virsh 命令
    qemu-img命令
    python logging
    oslo.messaging
    集成kafka的身份认证(SASL/PLAIN)到kubernets环境中
    Helm基础知识
  • 原文地址:https://www.cnblogs.com/cdcq/p/12362914.html
Copyright © 2011-2022 走看看