首页 > 其他分享 >P8865 [NOIP2022] 种花 题解

P8865 [NOIP2022] 种花 题解

时间:2023-10-26 22:59:06浏览次数:28  
标签:方案 int 题解 times P8865 NOIP2022 c2 c1

前言

去年多测不清空导致即便 CCF 放过了我的 \(O(n^2 m)\) 的代码但依然挂成了 \(0pts\)。

当时看清空数组后能过 CCF 数据就没再管。

时隔 \(1\) 年,重做这道题写了 \(O(nm)\) 的正解,终于完成了当年的心愿。

\(O(n^2 m)\) 思路

想到计算方案的话可以维护两个数组 \(c1_{i,j}\) 表示 \(i,j\) 位置上向右的最多连续 \(0\) 的个数,\(c2_{i,j}\) 表示 \(i,j\) 位置上向下的最多连续 \(0\) 的个数。

考虑以每个点为 \(c\) 形的左上角的那个点的方案数。

那么当前点 \((i, j)\) 的方案就是:

\[\sum_{k = i + 2}^{i + c2[i][j]} c1[i][j] \times c1[k][j] \]

当前行肯定不能算,下一行是 \(c\) 形中间的空行,所以从 \(i + 2\) 开始。

同样考虑以每个点为 \(f\) 形的左上角的点的方案数。

那么当前点 \((i, j)\) 的方案数就是:

\[\sum_{k = i + 2}^{i + c2[i][j]} c1[i][j] \times c1[k][j] \times (c2[i][j] - k) \]

最后那一块就是 \(f\) 形下面的小尾巴的方案。

然后我们就得到了一个 \(O(n^2 m)\) 的解法。

\(o(nm)\) 解法

发现全是 \(0\) 的时候上面的解法会被卡飞,所以考虑优化。

发现再对 \(c1[i][j]\) 的每一列做一次前缀和,用 \(c3\) 表示 \(c1[1][j]+ \dots + c1[i][j]\)。

然后我们可以利用前缀和 \(o(1)\) 计算每一个点 \(c\) 形的方案。

同理对于 \(f\) 形,我们维护类似拐角形的方案数,然后每列做一次前缀和,也能做到 \(o(1)\) 计算每一个点的 \(f\) 形的方案数。


/*
 * @Author: Aisaka_Taiga
 * @Date: 2023-10-26 21:02:05
 * @LastEditTime: 2023-10-26 22:22:57
 * @LastEditors: Aisaka_Taiga
 * @FilePath: \Desktop\P8865.cpp
 * The heart is higher than the sky, and life is thinner than paper.
 */
#include <bits/stdc++.h>

#define int long long
#define P 998244353
#define N 1100

using namespace std;

inline int read()
{
    int x = 0, f = 1;
    char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
    while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return x * f;
}

int n, m, c, f, a[N][N], c1[N][N], c2[N][N], c3[N][N], c5[N][N];
//c1每个点向右的零的个数,c2每个点向下的零的个数, c3每一列c2的前缀和,c5表示f形的下半部分当前点合法的数量。
//1h写了n^3的,80分
//1.5h终于把优化后的给写完了。

inline void qk()
{
    for(int i = 0; i <= n; i ++)
        for(int j = 0; j <= m; j ++)
            a[i][j] = c1[i][j] = c2[i][j] = c3[i][j] = c5[i][j] = 0;
    return ;
}

inline void work()
{
    qk();
    int ans1 = 0, ans2 = 0;
    n = read(), m = read(), c = read(), f = read();
    for(int i = 1; i <= n; i ++)
    {
        for(int j = 1; j <= m; j ++)
        {
            char cc;
            cin >> cc;
            a[i][j] = cc - '0';
        }
    }
    for(int i = 1; i <= n; i ++)
    {
        int t = 0;
        for(int j = m; j >= 1; j --)
        {
            if(a[i][j] == 0) t ++;
            else t = 0;
            c1[i][j] = (t == 0 ? 1 : t);
        }
    }
    for(int i = 1; i <= m; i ++)
    {
        int t = 0;
        for(int j = n; j >= 1; j --)
        {
            if(a[j][i] == 0) t ++;
            else t = 0;
            c2[j][i] = (t == 0 ? 1 : t);
        }
    }
    for(int j = 1; j <= m; j ++)
        for(int i = 1; i <= n; i ++)
            c3[i][j] = (c3[i - 1][j] + c1[i][j] - 1) % P,
            c5[i][j] = (c5[i - 1][j] + (c1[i][j] - 1) * (c2[i][j] - 1)) % P;
    for(int i = 1; i <= n - 2; i ++)
    {
        for(int j = 1; j <= m - 1; j ++)
        {
            if(c2[i][j] < 3) continue;
            ans1 = (ans1 + ((c1[i][j] - 1) * (c3[i + c2[i][j] - 1][j] - c3[i + 1][j])) % P) % P;
            if(c2[i][j] < 4) continue;
            ans2 = (ans2 + ((c1[i][j] - 1) * (c5[i + c2[i][j] - 1][j] - c5[i + 1][j])) % P) % P;
        }
    }
    cout << ans1 * c << " " << ans2 * f << endl;
    return ;
}

signed main()
{
    int T = read(), iid = read();
    while(T --) work();
    return 0;
}

标签:方案,int,题解,times,P8865,NOIP2022,c2,c1
From: https://www.cnblogs.com/Multitree/p/17790684.html

相关文章

  • SP4082 MBLAST - BLAST 题解
    几万年前做的dp题了,有亿点点水题意简述求一个字符串添加多少个空格距离最小解法求距离最小,可以考虑动规,其实这题的写法和最长公共子序列的写法类似。我们设\(f(i,j)\)表示\(a[1]\sima[i]\)和\(b[1]\simb[j]\)的距离不加空格的时候为\(f(i,j)=f(i-1,j-1)+\le......
  • [AGC061A] Long Shuffle 题解
    题意给定一个满足\(A_i=i\)的排列\(A\),求对其进行一次\(\mathrm{shuffle}(1,N)\)操作后其第\(K\)项的值。其中\(\mathrm{shuffle}(L,R)\)的定义如下:若\(R=L+1\),那么交换\(A_L\)和\(A_R\)的值否则,依次执行\(\mathrm{shuffle}(L,R-1)\),\(\mathrm{shuffle}(......
  • P4678 [BalticOI 2005] Bus Trip 题解
    P4678[BalticOI2005]BusTrip题解(RE:题解再改造!!)贴码#include<bits/stdc++.h>#defineMAXN500010usingnamespacestd;//ifstreamis("trip.in",ios::in);//ofstreamos("trip.out",ios::out);//#definecinis//#definecoutosintn,m,p,t,tote......
  • [HDU 3483] A Very Simple Problem 题解
    题目描述快速求出下面式子的值:\[\left(\sum\limits_{k=1}^{N}k^{x}x^{k}\right)\bmodM\]其中\(1≤N,M≤2\times10^9\),并且\(1≤x≤50\)。题解(solution)对于该类题目,\(N\)很大,而\(x\)很小,考虑矩阵快速幂优化。对于每一个\(N\)的答案,我们用\(f(N)\)来......
  • P5537 【XR-3】系统设计 题解-哈希+线段树二分
    20231026P5537【XR-3】系统设计题解-哈希+线段树二分这个东西怎么会和哈希有关?!直接寄。Statement这个系统首先需要输入一棵\(n\)个点的有根树和一个长度为\(m\)的序列\(a\),接下来需要实现\(q\)个操作。操作分两种:1xlr表示设定起点为有根树的节点\(x\),接下来......
  • CF888E题解
    分析看到\(n\leq35\)的数据范围就想到了meet-in-middle。先爆搜出对于\(1\sim\frac{n}{2}\)和\(\frac{n}{2}\simn\)两个下标范围内在模意义下所有的和。然后用一个常见trick,就是枚举第二个部分的和,然后匹配第一个部分的和的最优解。显然匹配有两种情况,一种是......
  • chrome新版本http自动跳转https问题解决
    虽然是个好功能,但是部分内网业务还没做好https兼容,有的时候手工访问,还是变成https 解决办法:chrome://flags/找到:HTTPSUpgrades,修改disabled,重启解决,当然这个需要需要用户去调整,真正还需要服务去兼容https  ......
  • 在使用 Unity 2022 打包安卓项目时,遇到 gradle 无法访问或下载超级慢最终超时出错的问
    一般表现是打包最后一步会等待超长时间,最后报错,错误信息:PickedupJAVA_TOOL_OPTIONS:-Dfile.encoding=UTF-8FAILURE:Buildfailedwithanexception.*Whatwentwrong:Aproblemoccurredconfiguringrootproject'Gradle'.>Couldnotresolveallartifactsfor......
  • CCC 2023 题解 和 思考过程
    Trianglane水题,只要分情况判断中间和两侧有边叠牢的情况,每次减2#include<iostream>#include<cstdlib>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>usingnamespacestd;typedeflonglongll;constintN=200010......
  • 「题解」Codeforces Round 905 (Div. 3)
    before终于有一篇题解是一次性更所有题的了。A.MorningProblemA.MorningSol&Code根据题意模拟即可。#include<bits/stdc++.h>typedeflonglongll;intmin(inta,intb){returna<b?a:b;}intmax(inta,intb){returna>b?a:b;}intT;int......