• luogu2467/bzoj1925 地精部落 (dp)


    求1~n组成一个抖动序列的方案数

    首先这种序列有一些非常妙妙但我发现不了的性质

    1.对于一个抖动序列,如果i和i+1不相邻,则交换i和i+1,他还是个抖动序列

    2.对于一个抖动序列,我把每个数拿n+1减一下(上下翻转),他还是个抖动序列,只不过波峰和波谷换了一下

    3.对于一个抖动序列,我把它左右翻转,他还是个抖动序列

    于是设f[i][j]是i个数中,排名为j的数在第一个位置、且它是波峰的方案数

    那么答案就是$2sum{f[N][i]}$(我把它翻一下不就有所有的第一个数作为波谷的情况了嘛)

    然后有方程$f[i][j]=f[i][j-1]+f[i-1][j-1]$

    考虑两种情况:

      1.j和j-1不相邻,由性质1这种情况的f[i][j]就是f[i][j-1]

      2.j和j-1相邻,也就是j-1在第二个位置,这种情况的f[i][j]就是f[i-1][j-1],就是不看j,然后把剩下的i-1个数拎出来,那j-1的排名还是j-1

    合起来就是上面的方程

     1 #pragma GCC optimize(3)
     2 #include<bits/stdc++.h>
     3 #define pa pair<ll,ll>
     4 #define CLR(a,x) memset(a,x,sizeof(a))
     5 using namespace std;
     6 typedef long long ll;
     7 const int maxn=4205;
     8 
     9 inline char gc(){
    10     return getchar();
    11     static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf;
    12     return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++;
    13 }
    14 inline ll rd(){
    15     ll x=0;char c=gc();bool neg=0;
    16     while(c<'0'||c>'9'){if(c=='-') neg=1;c=gc();}
    17     while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc();
    18     return neg?(~x+1):x;
    19 }
    20 
    21 int N,f[2][maxn],P;
    22 
    23 int main(){
    24     //freopen("","r",stdin);
    25     int i,j,k;
    26     N=rd(),P=rd();
    27     f[1][1]=1;
    28     for(i=2;i<=N;i++){
    29         for(j=1;j<=i;j++){
    30             f[i&1][j]=(f[i&1][j-1]+f[!(i&1)][i-j+1])%P;
    31         }
    32     }
    33     int ans=0;
    34     for(i=1;i<=N;i++)
    35         ans+=f[N&1][i],ans%=P;
    36     printf("%d
    ",ans*2%P);
    37     return 0;
    38 }
  • 相关阅读:
    人月神话阅读笔记之一
    第一阶段冲刺站立会议报告——9
    第一阶段冲刺站立会议报告——8
    第一阶段冲刺站立会议报告——7
    第一阶段冲刺站立会议报告——6
    第一阶段冲刺站立会议报告——5
    第二阶段冲刺第一天
    寻找水王2
    构建之法阅读笔记05
    第十二周学习进度条
  • 原文地址:https://www.cnblogs.com/Ressed/p/9935020.html
Copyright © 2020-2023  润新知