zoukankan      html  css  js  c++  java
  • [题解] [AGC013D] Piling Up

    题面

    题解

    把操作放到坐标轴上, (y) 轴代表黑球个数, (x) 球代表操作次数

    然后对应的操作就可以看作加上 ((1, 1))((1, -1)) 的两个向量

    于是对应的操作序列就变为了一根折线

    但是有可能会有重复的情况

    我们只计算到达过 (x) 轴的那一根

    并且这是肯定可以实现的

    于是我们设 (f[i][j][0 / 1]) 代表前 (i) 次操作, 黑球还有 (j) 个, 没有 / 有经过 (0)

    转移的话是这样的

    假如说这次拿出了两个黑球

    (f[i - 1][j][1] o f[i][j - 1][1] (j geq 1)) , (f[i - 1][j][0] o f[i][j - 1][0] (j geq 2)) , (f[i - 1][j][0] o f[i][j - 1][1] (j = 1))

    拿了两个白球

    (f[i - 1][j][0 / 1] o f[i][j + 1][0 / 1] (j < n))

    这次拿了先黑再白

    (f[i - 1][j][1] o f[i][j][1] (j leq 1)) , (f[i - 1][j][0] o f[i][j][0] (j leq 2)) , (f[i - 1][j][0] o f[i][j][1] (j = 1))

    这次拿了先白再黑

    (f[i - 1][j][0 / 1] o f[i][j][0 / 1] (j < n))

    答案就是 (sum_{j = 0}^{n} f[m][j][1])

    Code

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    const int N = 3005;
    const int mod = 1000000007; 
    using namespace std;
    
    int n, m, f[N][N][2], ans; 
    
    template < typename T >
    inline T read()
    {
    	T x = 0, w = 1; char c = getchar();
    	while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * w; 
    }
    
    int main()
    {
    	n = read <int> (), m = read <int> ();
    	for(int i = 1; i <= n; i++)
    		f[0][i][0] = 1;
    	f[0][0][1] = 1;
    	for(int i = 1; i <= m; i++)
    		for(int j = 0; j <= n; j++)
    		{
    			if(!j)
    			{
    				f[i][j][1] = f[i - 1][j][1];
    				if(j < n) f[i][j][1] = (1ll * f[i][j][1] + f[i - 1][j + 1][1] + f[i - 1][j + 1][0]) % mod; 
    			}
    			else if(j == 1)
    			{
    				if(j < n) f[i][j][0] = (f[i][j][0] + f[i - 1][j + 1][0] + f[i - 1][j][0]) % mod; 
    				f[i][j][1] = (1ll * f[i - 1][j][1] + f[i - 1][j][0] + f[i - 1][j - 1][1]) % mod;
    				if(j < n) f[i][j][1] = (1ll * f[i - 1][j + 1][1] + f[i][j][1] + f[i - 1][j][1]) % mod; 
    			}
    			else
    			{
    				f[i][j][0] = (1ll * f[i - 1][j][0] + f[i - 1][j - 1][0]) % mod; 
    				f[i][j][1] = (1ll * f[i - 1][j][1] + f[i - 1][j - 1][1]) % mod;
    				if(j < n)
    				{
    					f[i][j][0] = (1ll * f[i][j][0] + f[i - 1][j][0] + f[i - 1][j + 1][0]) % mod;
    					f[i][j][1] = (1ll * f[i][j][1] + f[i - 1][j][1] + f[i - 1][j + 1][1]) % mod;
    				}
    			}
    		}
    	for(int i = 0; i <= n; i++)
    		ans = (1ll * ans + f[m][i][1]) % mod; 
    	printf("%d
    ", ans); 
    	return 0; 
    }
    

    在洛谷上蒯的第一篇题解的转移方程, 不想写了

  • 相关阅读:
    go语言正则
    20个简洁的js代码片段
    笔记本连接WiFi提示“无法连接此网络”解决方法总结
    gitlab-cicd常见问题
    Angular服务器渲染常遇的坑
    一次页面性能问题排查的过程
    短链接生成工具(好用)
    MySQL分页查询
    2021精选 Java面试题附答案(一)
    CSRF攻击原理及防护
  • 原文地址:https://www.cnblogs.com/ztlztl/p/12199639.html
Copyright © 2011-2022 走看看