• CF 1027E Inverse Coloring


    当天晚上并没有看懂题意,然后就刚了40分钟F,但是没有弄出来呜呜呜。

    推荐博客:  https://blog.csdn.net/Dream_maker_yk/article/details/81840495

    考虑到我们写出一行和一列的情况就可以还原出整个正方形,而这一行和这一列的长度是一样的,所以我们可以合在一起dp。

    我们设$f_{i, j}$表示在前$i$个格子中最长的一个颜色的长度为$j$的方案数,有转移方程:

        $f_{i, j} = sum_{j = 1}^{i}sum_{k = 1}^{j}f_{i - k, min(j, i - k)}$

    注意到这时候我们算出来的$f_{i, j}$实际上是包含了$f_{i, j - 1}, f_{i, j - 2}...$的情况的,所以我们再差分一遍使$f_{i, j}$的定义表示为长度为$i$的序列中最长的连续相同的颜色段恰好为$j$的方案数。

    然后我们只要枚举这个连续的最长段的长度去累加答案就好了,其实到现在为止我们都只是计算了一种颜色的情况,考虑到把黑白格子反一反就可以得到完全相同的另外的合法情况,所以最后把答案乘以二。

    枚举时注意小细节$j$的范围要小于$n$,我就是这样RE了一次。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    const int N = 505;
    const ll P = 998244353LL;
    
    int n, siz;
    ll f[N][N];
    
    inline int min(int x, int y) {
        return x > y ? y : x;
    }
    
    int main() {
        scanf("%d%d", &n, &siz);
        
        f[0][0] = 1LL;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= i; j++)
                for(int k = 1; k <= j; k++)
                    f[i][j] = (f[i][j] + f[i - k][min(j, i - k)]) % P;
        for(int i = n; i >= 1; i--)
            f[n][i] = (f[n][i] - f[n][i - 1] % P + P) % P;
            
    /*    for(int i = 1; i <= n; i++)
            printf("%lld ", f[n][i]);
        printf("
    ");   */
        
        ll ans = 0LL;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j * i < siz && j <= n; j++)
                ans = (ans + f[n][i] * f[n][j] % P) % P;
        ans = ans * 2 % P;
        printf("%lld
    ", ans);
        
        return 0;
    }
    View Code
  • 相关阅读:
    C# Firefox Session Manager 文件的导出与管理
    安徒生的童话《冰雪皇后》原本是这样的
    许多人不知道的生活小秘方
    洗衣服窍门大全
    小窍门解决大问题(绝对值得收藏)
    日常生活小技巧
    谷歌浏览器应用商店打不开,下载不了扩展程序的解决办法
    食品安全如何让百姓放心
    把 WORD 里的换行符(向下的箭头)换成回车符(常用回车符)
    充满创意的生活小妙招 --爱生活爱创意!
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9517371.html
Copyright © 2020-2023  润新知