noip2022种花

noip2022 T1 种花

题目链接

本题可以运用一个前缀和,用prei,j表示第i行,从右往左推出的第j列的前缀和。算完前缀和以后枚举每一个C的转折点。对于一个C,只要在它的下面添加几行即可成为F,所以不用单独求F,只需要求出 C 即可。求C时要用到乘法原理,即一共的方案数的计算。


part1

计算前缀和:当当前的土坑不能种花时,prei,j设成1,否则就等于上一个+1,在转折点出的数字就是这一行的方案数量。

for(int i=1; i<=n; i++){
    for(int j=m-1; j>=1; j--){
        if(t[i][j]=='1'){
            pre[i][j]=-1;
        }
        else if(t[i][j+1]=='0'){
            pre[i][j]=pre[i][j+1]+1;
        }
    }
}

part2

前缀和计算完成,接下来就是进行对C的转折点的枚举。题目中对C的要求就是两行中间至少要间隔一行,所以在进行乘法计算的时候是不加上上一行的,乘法结束后再加上上一行。此外,对于F的计算就是在C的基础上加上下面的一列,可以直接用C来求出。
优化: 不计算最后一列,因为不存在任何的CF

for(int j=1; j<m; j++){
    int hc=0,hf=0;
    for(int i=1; i<=n; i++){
        if(pre[i][j]==-1){//相当于挡住了下面的
            hc=0,hf=0;
            continue;
        }
        ansc+=hc*pre[i][j];
        ansf+=hf;
        hf+=hc*pre[i][j];//求出到当前有多少合法的C
        hc+=max(0,pre[i-1][j]);//计算完成后再加上上一行的
    }
}

完整的代码需要取模,有T组数据,数组需要清空或在循环内定义数组


part3

ACcode

#include<vector>
#include<iostream>
#define endl "\n"
#define int long long
using namespace std;

const int mod=998244353;

int max(int a,int b){
    return a>b ? a:b;
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    //cout.tie(0);
    int t,id;
    cin>>t>>id;
    while(t--){
        int n,m,c,f;
        cin>>n>>m>>c>>f;
        vector<vector<char>> t(n+100,vector<char>(m+100));
        vector<vector<int>> pre(n+100,vector<int>(n+100,0));
        for(int i=1; i<=n; i++){
            for(int j=1; j<=m; j++){
                cin>>t[i][j];
            }
        }
        for(int i=1; i<=n; i++){
            for(int j=m-1; j>=1; j--){
                if(t[i][j]=='1'){
                    pre[i][j]=-1;
                }
                else if(t[i][j+1]=='0'){
                    pre[i][j]=pre[i][j+1]+1;
                }
            }
        }
        int ansc=0,ansf=0;
        for(int j=1; j<m; j++){
            int hc=0,hf=0;
            for(int i=1; i<=n; i++){
                if(pre[i][j]==-1){
                    hc=0,hf=0;
                    continue;
                }
                ansc+=(hc*pre[i][j]*1ll)%mod;
                ansf+=hf%mod;
                hf+=(hc*pre[i][j]*1ll)%mod;
                hc+=max(0,pre[i-1][j]);
                hc%=mod;
            }
        }
        cout<<(ansc*c)%mod<<" "<<(ansf*f)%mod<<endl;
    }
    return 0;
}
posted @   lwr2010  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示