当前位置: 首页 > news >正文

AtCoder Beginner Contest 338 G. evall(枚举+递推 统计贡献)

题目

长为1e6的串,只由数字1-9、加号+、乘号*组成,

对1<=i<=j<=n,只要s[i]和s[j]均为数字,就将eval(i,j)(求值表达式)的值加入答案内

求答案对998244353取模的值

换言之,求以下程序的结果

s = input()
n = len(s)
ans, mod = 0, 998244353
def ok(x):return '0'<=x<='9'
for i in range(n):for j in range(i,n):if ok(s[i]) and ok(s[j]):ans = (ans + eval(s[i:j+1])) % mod
print(ans)

思路来源

乱搞ac

题解

把连乘的段单独处理,统计每一段的贡献

如果左侧顶到一个+号,那么加号往左的都可以取,右侧同理

如果左侧不是加号,那么左侧只能卡到i 

1234*2345*3456

枚举i=2时,这一位的贡献有:

2 23 234

234*2 234*23 234*234 234*2345

234*2345*3 234*2345*34 234*2345*345 234*2345*3456

发现需要处理一个形如(3+34+345+3456)的东西,

还需要处理一个形如2345*(3+34+345+3456)的东西,并加上2+23+234

于是开了一堆数组维护这些内容,

pre[i]表示i前有几个数字,suf[i]表示i后有几个数字

尺取相邻加号之间的段,处理连乘的贡献,

不妨称3+34+345+3456这样的段,叫3456这个数的前缀贡献

sum[i]形如(3+34+345+3456)+(2+23+234+2345),

只需要某个数的前缀贡献的时候,作差得到

sum2[i]形如2+23+234+2345*(3+34+345+3456),

转移要么乘上一个数,要么加上这个数的前缀贡献,可以递推实现

由4+45+456需要得到3+34+345+3456时,加上3333即可,

所以ten[i]维护10的幂次,形如1000,sten[i]维护其前缀和,形如1111

las[i]记录i这个位置后面的第一个符号的位置,可能为乘号或者加号

now[i]记录i这个位置所在的段往后延伸到尾部时,这个数字是多少

mul[i]表示i这个位置往后的第一个完整的数到尺取段尾这一段区间的积是多少

比如1+23*45*56+7,mul[4]表示45*56的值,而mul[3]表示23*45*56的值

总之,就是通过手玩发现,需要通过枚举+数贡献的方式计数,然后就是xjb乱搞

代码

#include<bits/stdc++.h>
#include<cstdio>
#include<vector>
#include<map>
#include<queue>
#include<array>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
const int N=1e6+10,mod=998244353;
char s[N];
int n,pre[N],suf[N],sum[N],sum2[N],mul[N];
int ten[N],sten[N],cur,w,las[N],now[N],ans;
void add(int &x,int y){x=(x+y)%mod;
}
bool ok(char x){return '0'<=x && x<='9';
}
int cal(int l,int r){return (sum[l]-sum[r+1]+mod)%mod;
}
int main(){scanf("%s",s+1);n=strlen(s+1);s[0]=s[n+1]='+';ten[0]=sten[0]=1;rep(i,1,n){ten[i]=10ll*ten[i-1]%mod;sten[i]=(sten[i-1]+ten[i])%mod;}rep(i,1,n){pre[i]=pre[i-1]+ok(s[i]);}per(i,n,1){suf[i]=suf[i+1]+ok(s[i]);}for(int j=n+1;j>=0;){if(s[j]=='+'){mul[j]=1;las[j]=j;j--;continue;}int k=j;while(k && s[k]!='+')k--;cur=w=0;for(int i=j;i>k;--i){las[i]=las[i+1];sum[i]=sum[i+1];sum2[i]=sum2[i+1];mul[i]=mul[i+1];if(s[i]=='*'){cur=w=0;las[i]=i;continue;}cur++;int v=s[i]-'0';w=(w+1ll*v*ten[cur-1]%mod)%mod;now[i]=w;sum[i]=(sum[i+1]+1ll*v*sten[cur-1]%mod)%mod;//printf("i:%d sum2i:%d\n",i,sum2[i]);if(!ok(s[i-1])){sum2[i]=cal(i,las[i]-1)%mod;sum2[i]=(sum2[i]+1ll*w*sum2[las[i]]%mod)%mod;mul[i]=1ll*mul[i]*w%mod;}//printf("i:%d sum:%d sum2:%d las:%d cal:%d w:%d pre:%d\n",i,sum[i],sum2[i],las[i],cal(i,las[i]-1),w,sum2[las[i]]);}for(int i=k+1;i<=j;++i){if(s[i]=='*')continue;int w1=1ll*now[i]*sum2[las[i]]%mod;//*后面的sum2 和*前面结尾1的贡献 左端点在i 右端点在las[i]+号左的贡献int bs=(i==k+1?pre[k]+1:1);//左侧+左的也可以取(i=k+1时可以再往左任取)int w2=1ll*now[i]*mul[las[i]]%mod*suf[j+1]%mod;//右侧+右的也可以取 左端点在i 右端点在las[i]+号右的贡献int w3=cal(i,las[i]-1);w=(w1+w2)%mod;w=(w+w3)%mod;w=1ll*w*bs%mod;ans=(ans+w)%mod;//printf("i:%d s:%d las:%d now:%d bs:%d sum2lasi:%d w1:%d w2:%d w3:%d w:%d ans:%d\n",i,s[i]-'0',las[i],now[i],bs,sum2[las[i]],w1,w2,w3,w,ans);}j=k;}printf("%d\n",ans);return 0;
}
//2*(2+2*3+2*34)
/*
1*mul[2]
1*2*mul[3]
1*2*3*mul[4]
mul[3]+3*mul[4]
当前数做积2345*(3+34+345+3456)
+2+23+234+2345
每一段先乘完整数 然后加mul
两层递推
*/
/*
1+10*11+2
1 (2)
10 (2) 
10*1 (2)
10*11 (4)
*//*8 8*3 8*3*3 8*3*33*/

相关文章:

  • 【QT+QGIS跨平台编译】之二十六:【SpatialIndex+Qt跨平台编译】(一套代码、一套框架,跨平台编译)
  • 金和OA jc6 UploadFileBlock 任意文件上传漏洞复现
  • 学成在线:媒体资源管理系统(MAM)
  • onnx转换为rknn置信度大于1,图像出现乱框问题解决
  • 企业级IT应用运维监控:层次架构设计与实践指南
  • TOP100 矩阵
  • 前后端数据校验
  • Linux 网络编程 + 笔记
  • BUUCTF-Real-[ThinkPHP]5-Rce
  • TPM 2.0安全算法开发示例实战 | 开发准备
  • 07-使用Package、Crates、Modules管理项目
  • 多维时序 | Matlab实现CNN-RVM卷积神经网络结合相关向量机多变量时间序列预测
  • Spring 事务原理总结三
  • MySQL中如何将字符串替换
  • C# 怎么判断屏幕是第几屏幕?屏幕是垂直还是水平?屏幕的分辨率?
  • [case10]使用RSQL实现端到端的动态查询
  • 30天自制操作系统-2
  • 4. 路由到控制器 - Laravel从零开始教程
  • Android Studio:GIT提交项目到远程仓库
  • android 一些 utils
  • Babel配置的不完全指南
  • es的写入过程
  • Median of Two Sorted Arrays
  • mysql常用命令汇总
  • PhantomJS 安装
  • session共享问题解决方案
  • underscore源码剖析之整体架构
  • 笨办法学C 练习34:动态数组
  • 从PHP迁移至Golang - 基础篇
  • 从伪并行的 Python 多线程说起
  • 前端面试之CSS3新特性
  • 如何用vue打造一个移动端音乐播放器
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • Prometheus VS InfluxDB
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 如何在招聘中考核.NET架构师
  • #《AI中文版》V3 第 1 章 概述
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • (6)设计一个TimeMap
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (三) diretfbrc详解
  • (四)库存超卖案例实战——优化redis分布式锁
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • (转载)OpenStack Hacker养成指南
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET Framework 4.6.2改进了WPF和安全性
  • .Net Web窗口页属性
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • ::before和::after 常见的用法
  • @AliasFor注解