zoukankan      html  css  js  c++  java
  • BZOJ 4321 queue2

    4321: queue2

    Description

    n 个沙茶,被编号 1~n。排完队之后,每个沙茶希望,自己的相邻的两人只要无一个人的编号和自己的编号相差为 1(+1 或-1)就行; 现在想知道,存在多少方案满足沙茶们如此不苛刻的条件。 

    Input

    只有一行且为用空格隔开的一个正整数 N,其中 100%的数据满足 1≤N ≤ 1000; 

    Output

    一个非负整数,表示方案数对 7777777 取模。   

    Sample Input

    4

    Sample Output

    2
    样例解释:有两种方案 2 4 1 3 和 3 1 4 2

      这道题还真没想到是DP。
      去年NOIP考前看到此题,当时竟不知DP,只会暴力。至此便叹息痛恨焉。
      昨夜又见,虽欣喜,然不知何为。
      直到我看见:【bzoj4321】queue2
      啊啊啊啊啊!这篇博客已经讲得很详细了。这n个沙茶可以一个一个插入。
      状态表示:f[i][j][0..1]=前i个沙茶有j对是相邻的,其中第i个沙茶和第i-1个沙茶相不相邻
      初始状态:f[1][0][0]=1
      状态转移:
      f[i][j][1]<-f[i-1][j][1] 第i个沙茶插在了第i-1个和第i-2个之间
                        <-f[i-1][j-1][1] 第i个沙茶插在了第i-1个旁边,第i-2个的另一侧
                        <-f[i-1][j-1][0]*2 第i个沙茶插在了第i-1个的左右两侧(第i-1个不与第i-2个相邻)
      f[i][j][0]<-f[i-1][j+1][1]*j 第i个沙茶落了单,干坏事。可以拆散j对,因为不能拆散第i-1个和第i-2个
                        <-f[i-1][j+1][0]*(j+1) 第i个沙茶落了单,干坏事。可以拆散j+1对
                        <-f[i-1][j][1]*(i-j-1) 第i个沙茶落了单,兀自玩去了。(i-1+1)-(j+1),不能拆散j对也不能在第i-1个旁边
                        <-f[i-1][j][0]*(i-j-2) 第i个沙茶落了单,兀自玩去了。(i-1+1)-(j+2),不能拆散j对也不能在第i-1个旁边
      答案输出:ans=f[n][0][0]
      可用滚动数组。时间O(n^2),空间O(n)。
      不过还有递推式:http://oeis.org/A002464 f[n]=(n+1)f[n1](n2)f[n2](n5)f[n3]+(n3)f[n4]
      此题转移中分类讨论很有意思,是一道很好的题。注意不要爆int。
     1 /**************************************************************
     2     Problem: 4321
     3     User: Doggu
     4     Language: C++
     5     Result: Accepted
     6     Time:484 ms
     7     Memory:852 kb
     8 ****************************************************************/
     9  
    10 #include <cstdio>
    11 long long n, f[2][1010][2], cur, MOD=7777777;
    12 inline void add(long long &a,long long b) {if(b>MOD) b%=MOD;a=a+b>MOD?a+b-MOD:a+b;}
    13 int main() {
    14     scanf("%d",&n);
    15     f[cur][0][0]=1;
    16     for( int i = 2; i <= n; i++ ) {
    17         cur^=1;
    18         for( int j = 0; j <= i-1; j++ ) {
    19             f[cur][j][1]=f[cur^1][j][1];
    20             if(j) add(f[cur][j][1],f[cur^1][j-1][1]);
    21             if(j) add(f[cur][j][1],f[cur^1][j-1][0]*2);
    22             f[cur][j][0]=f[cur^1][j+1][1]*j;
    23             add(f[cur][j][0],f[cur^1][j+1][0]*(j+1));
    24             add(f[cur][j][0],f[cur^1][j][1]*(i-j-1));
    25             add(f[cur][j][0],f[cur^1][j][0]*(i-j-2));
    26         }
    27     }
    28     printf("%d
    ",f[cur][0][0]);
    29     return 0;
    30 }
    31 
    DP
     
  • 相关阅读:
    Scala (三)集合
    为什么成为一名程序员?
    Hadoop——Yarn
    Redis(一)NoSQL简介、Redis安装 、数据类型、配置文件、发布订阅
    Java并发编程——共享模型之内存( JMM、原子性、可见性、有序性、volatile原理)
    KafkaAPI实战案例
    分布式技术原理笔记(二)分布式体系结构
    Flume 进阶
    Kafka框架基础
    Scala (二)面向对象
  • 原文地址:https://www.cnblogs.com/Doggu/p/bzoj4321.html
Copyright © 2011-2022 走看看