noip2018普及组初赛解析_NOIP复赛

noip2018普及组初赛解析_NOIP复赛博主是一个高中生,在进行noip训练的时候遇到这一题,当时写了2个多小时惭愧啊惭愧,只能感叹一声普及组好可怕!!!然而这题在code.vs里只有黄金。。。我现在很怀疑自己是怎么做出那些大师题的。。。原题链接在此:http://codevs.cn/problem/1133/好了,现在我们来分析一下这个题目。这个题目中读入的字符串是只有‘*’、‘+’、‘(‘和’)‘的,而

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

本题大意如下:

NOIP2011普及组——表达式的值

Description

对于1 位二进制变量定义两种运算:
运算规则
0 ⊕0=0
0 ⊕1=1
1 ⊕0=1
1 ⊕1=1
0 × 0=0
0 × 1=0
1 × 0=0
1 × 1=1
运算的优先级是:
1. 先计算括号内的,再计算括号外的。
2. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算。
例如:计算表达式A⊕B × C时,先计算 B × C,其结果再与 A 做⊕运算。 现给定一个未完成的表达式,例如+(_*),请你在横线处填入数字0 或者1 ,请问有多少种填法可以使得表达式的值为0 。

Input

第1 行为一个整数 L,表示给定的表达式中除去横线外的运算符和括号的个数。
第2行为一个字符串包含 L 个字符,其中只包含’(’、’)’、’+’、’’这4 种字符,其中’(’、’)’是左右括号,’+’、’’分别表示前面定义的运算符“⊕”和“×”。这行字符按顺序给出了给定表达式中除去变量外的运算符和括号。

Output

输出文件exp.out 共1 行。包含一个整数,即所有的方案数。注意:这个数可能会很大,请输出方案数对10007 取模后的结果。

Sample Input

4
+(*)

Sample Output

3

Data Size & Hint

给定的表达式包括横线字符之后为:+(_*)?
在横线位置填入(0 、0 、0) 、(0 、1 、0) 、(0 、0 、1) 时,表达式的值均为0 ,所以共有3种填法。?
【数据范围】
对于20% 的数据有 0 ≤ L ≤ 10。
对于50% 的数据有 0 ≤ L ≤ 1,000。
对于70% 的数据有 0 ≤ L ≤ 10,000 。
对于100%的数据有 0 ≤ L ≤ 100,000。
对于50% 的数据输入表达式中不含括号。

博主是一个逗逼的高中生,在进行noip训练的时候遇到这一题,当时写了2个多小时
惭愧啊惭愧,
只能感叹一声普及组好可怕!!!
然而这题在code.vs里只有黄金。。。
我现在很怀疑自己是怎么做出那些大师题的。。。
原题链接在此:
http://codevs.cn/problem/1133/
好了,现在我们来分析一下这个题目。
这个题目中读入的字符串是只有‘*’、‘+’、‘(‘和’)‘的,而左右括号是互相配对的,优先级最高。
因此我们可以在栈中加入左括号的位置,在遇见右括号的时候依次取出栈中的值即可
在计算时有意思的是这个式子中是没有数字的,原题只是需要计算填完数字后值为0的情况总数而已
这个时候一些码农同志们可能就会不考虑复杂度直接开敲
给各个位置都填上数值,最后check。。。
这种人我也是醉了,博主对此不作评价
而正常人在开敲每道题的代码之前总是会总结一些什么的
在这一道题中
如果我们把数对(a,b)当做一个数Si分别为为0、1的情况数
那么很容易可以得出:

  • (a,b)*(c,d)=(ac+bc+ad,bd);
  • (a,b)+(c,d)=(ac,bc+ad+bd);

知道了这个性质之后同志们就可以开始敲代码了,每次把括号中的值算好后储存在左括号的位置即可
需要注意的是循环中的下标的变化并能连续的,否则复杂度为O(n^2)会超时
这个时候就需要一点简单的小技巧了,每次计算完一个括号中的值时,将左括号的nxt指向右括号,保证不重复遍历某一子串。
而且这个解法如果使用c++数据库中的string可以简单很多,好吧,其实没啥区别
代码如下:

//PS:原题有特别说明,将结果mod10007
#include<string>
#include<vector>
#include<iostream>
using namespace std;
#define M 300005
#define P 10007
string str;
int pre[M],nxt[M];
struct node{
    int a,b;
    node init(){
  
  //初始化每个数为0或1的情况数
        a=1;b=1;
    }
}ans,res[M];
struct li{
    int l,r;
};
vector<li>edge;
void add(node &A,node B){
    node C;
    C.a=(A.a*B.a)%M;
    C.b=(A.a*B.b+A.b*B.a+A.b*B.b)%M;
    A=C;
}// 加法计算
void mul(node &A,node B){
    node C;
    C.a=(A.a*B.a+A.a*B.b+A.b*B.a)%M;
    C.b=A.b*B.b%M;
    A=C;
}//乘法运算
int main(){
    int n;
    cin>>n;
    cin>>str;
    str.insert(0," ");
    for(int i=0;i<str.length();i++)res[i].init();
    int top=0;
    for(int i=0;i<str.length();i++){
        if(str[i]=='(')pre[top++]=i;
        else if(str[i]==')'){
            int p=pre[--top],s=p,cnt=0;
            li tmp;
            tmp.l=p,tmp.r=i;
            edge.push_back(tmp);
        }//好吧,这里是博主智障了,其实完全可以再加上1层for直接计算括号中的值。
       //反正仍旧是O(n)复杂度
        //(其实这里是博主当初敲O(n^2)WA代码的时候想的优化,然而似乎并没有什么软用)
    }for(int i=0;i<str.length();i++)nxt[i]=i+1;
    for(int k=0;k<edge.size();k++){
        li tmp=edge[k];
        int p=tmp.l,i=tmp.r,s=p;
        for(int j=p+1;j<i;j=nxt[j])
            if(str[j]=='(')res[j-1]=res[j];//将括号中计算好的结果导出
        for(int j=p+1;j<i;j=nxt[j]){
            if(str[j]=='*')mul(res[s],res[j]);//先计算乘法
            else if(str[j]=='+')s=j;//若遇到加号,略过它,并且之后的乘法需要累加到这个加号上。。
                                        //这一点相信有点智商的小朋友都能明白
        //至于为什么要累加到加号上,这纯粹是因为博主不想在运算符之中插入一个个空格,影响式子的美感罢了
        }s=p;                                                      //(好吧,我承认我懒。。)
        for(int j=p+1;j<i;j=nxt[j])
            if(str[j]=='+')add(res[s],res[j]);//最后再进行加法运算
        nxt[p]=i;//将左括号的nxt指向右括号
    }
    //*
    for(int i=1;i<str.length();i=nxt[i])
        if(str[i]=='(')res[i-1]=res[i];
    int s=0;
    for(int i=1;i<str.length();i=nxt[i]){
        if(str[i]=='*')mul(res[s],res[i]);
        else if(str[i]=='+')s=i;
    }s=0;
    for(int i=1;i<str.length();i=nxt[i])
        if(str[i]=='+')add(res[s],res[i]);
        *//中间带注释的这一段你可以选择略过它,
     //因为这本就是博主一时懵逼敲的。。
    //后来才察觉,可以直接用string.insert往整个式子的开头和末尾在插入一对括号就行了。。。 
    cout<<res[0].a<<endl;
    return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/189734.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • VXLAN基本概述

    VXLAN基本概述

    2021年4月16日
    156
  • 北京移动全网优惠_随着竞争的加剧

    北京移动全网优惠_随着竞争的加剧 【eNet硅谷动力消息】被叫全免计划终于推出了,这个计划可以说是大家翘首以盼,许多人大大节省了话费,对很多人来说是一个大大的福音,但也因此造成了中国通讯资费的改革提速,从而加剧了行业之间的竞争。  中移动北京公司市场部负责人介绍,5月23日公司正式推出了全球通标准资费“被叫全免计划”。自即日开始,北京地区的全球通客户切实实现被叫免费,接听时间没有限制,进一步呼应了社会的期盼。按照本次…

    2022年10月7日
    0
  • DVWA之反射型XSS代码审计

    DVWA之反射型XSS代码审计目录lowmediumhighimpossible从整个cms的角度去分析这个漏洞low前端代码如下。定义了一个表达以get的方式发送请求形式为?name=。然后包含了一个$html的变量源码如下。array_key_exists()函数检查某个数组中是否存在指定的键名,如果键名存在则返回true,如果键名不存在则返回false。$_GET为超全局变量。直接将输入的name值赋值给变量$html然后前端再引用这个变量,所以触发xss<?php.

    2022年6月2日
    28
  • CNN简单实战:pytorch搭建CNN对猫狗图片进行分类

    CNN简单实战:pytorch搭建CNN对猫狗图片进行分类上一篇文章介绍了使用pytorch的Dataset和Dataloader处理图片数据,现在就用处理好的数据对搭建的CNN进行训练以及测试。

    2022年6月12日
    24
  • er图是什么样的_er图形状代表什么意思

    er图是什么样的_er图形状代表什么意思数据模型(DataModel)是数据特征的抽象。数据模型所描述的内容包括三个部分(三个要素):数据结构、数据操作、数据约束。数据模型分为两类:第一类和第二类。第一类就是概念模型,ER图就是概念模型的一种表示方法。ER图:实体-关系图。是用来描述现实世界的一种概念模型。包括三个要素:实体(矩形)、属性(椭圆)、关系(菱形)。关系要标明类型:1对多、1对1、多对多等关系。第二类包括逻辑…

    2022年9月22日
    0
  • .ziw文件是什么?如何打开.ziw文件?[通俗易懂]

    .ziw文件是什么?如何打开.ziw文件?[通俗易懂].ziw文件是为知笔记的一种文档格式打开方式:找到为知笔记的官网,下载它的windows安装包即可[缺点:该软件会有一个使用的有效期]打开.ziw文件时,右击选择发送到“为知笔记”,选择相应的文件夹保存即可…

    2022年10月12日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号