首页 > 其他 > 详细

【AGC013D】Piling Up

时间:2020-01-15 21:07:27      阅读:94      评论:0      收藏:0      [点我收藏+]

题面

洛谷

题解

将每一轮操作之后的状态看作一条折线,其中横坐标是第\(i\)轮操作,纵坐标是剩余黑球的个数。

那么构建一条折线的方案就对应了一类不同的放球序列,

但是如果几条折线你可以上下平移得到就算重了,要保证不重的话,直接让最低点在\(x\)轴上即可。

\(f_{i,j,0/1}\)表示当前在第\(i\)轮,剩\(j\)个黑球,最低点是否到达过\(x\)轴,分类讨论一下即可。

代码

#include <iostream> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
using namespace std; 
const int Mod = 1e9 + 7; 
const int MAX_N = 3e3 + 5; 
int N, M; 
int f[MAX_N][MAX_N][2]; 
void pls(int &x, int y) { x += y; if (x >= Mod) x -= Mod; } 
int main () { 
    cin >> N >> M; 
    f[0][0][1] = 1; 
    for (int i = 1; i <= N; i++) f[0][i][0] = 1; 
    for (int i = 0; i < M; i++) 
        for (int j = 0; j <= N; j++) { 
            if (j >= 1) {
                //2 black
                pls(f[i + 1][j - 1][1], f[i][j][1]); 
                if (j == 1) pls(f[i + 1][j - 1][1], f[i][j][0]); 
                else pls(f[i + 1][j - 1][0], f[i][j][0]); 
            } 
            if (j < N) { 
                //2 white
                pls(f[i + 1][j + 1][1], f[i][j][1]); 
                pls(f[i + 1][j + 1][0], f[i][j][0]); 
            } 
            if (j >= 1) { 
                //1 black 1 white 
                pls(f[i + 1][j][1], f[i][j][1]); 
                if (j == 1) pls(f[i + 1][j][1], f[i][j][0]); 
                else pls(f[i + 1][j][0], f[i][j][0]); 
            } 
            if (j < N) { 
                //1 white 1 black 
                pls(f[i + 1][j][1], f[i][j][1]); 
                pls(f[i + 1][j][0], f[i][j][0]); 
            } 
        } 
    int ans = 0; 
    for (int i = 0; i <= N; i++) pls(ans, f[M][i][1]); 
    printf("%d\n", ans); 
    return 0; 
} 

【AGC013D】Piling Up

原文:https://www.cnblogs.com/heyujun/p/12198609.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!