最近举办了一场校赛,但是因为老师忘记提醒我们了,所以这场比赛就变成了训练赛,让我们自己完成。比赛中我有了思路,因为做过和这类似的题目---最大连续子区间积 以及和这类问题。所以有了思路,应该是用dp来完成。但在比赛时间内我并没有完成,在赛后补题时才把它写完(还是太菜了)。
# 问题描述: 链接:https://ac.nowcoder.com/acm/contest/20033/B 来源:牛客网
给你一个长度为n的数组{1<=n<=10^5}1<=n<=10 5,每个元素值为{2^x}
或者{-2^x},(-100 < x < 100) ,(−100<x<100),你可以定义一个区间[L, R](1 <= L <= R <= n),然后把该数组在[L, R]区间内所有的元素累乘得到一个ans,求最大的ans(个位为{2^x},假如ans 为 1,那么输出{2^0} )
首先这一看就是字符输入的,为了处理数据,我们得把字符转成数字
代码如下(示例):
int n,a[100010],c[100010];
string b[100010];
cin>>n;
for(int i=0;i<n;i++)
{
cin>>b[i];
//cout<<b[i].size()<<endl;
}
for(int i=0;i<n;i++)
{
if(b[i][0]=='-')
{
c[i]=-1;
if(b[i][3]=='-')
{
int x=0;
for(int j=4;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
//if(x%2==0)c[i]=1;
q[i].z=0;
q[i].m=x;
}
else
{
int x=0;
for(int j=3;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
//if(x%2==0)c[i]=1;
q[i].z=x;
q[i].m=0;
}
}
else
{
c[i]=1;
if(b[i][2]=='-')
{
int x=0;
for(int j=3;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
q[i].z=0;
q[i].m=x;
}
else
{
int x=0;
for(int j=2;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
q[i].z=x;
q[i].m=0;
}
}
}
后边就用类似最大连续子区间和以及积的想法来写。
类似于这样:
maxTmp = Math.max(a[i], Math.max(maxCur * a[i], minCur * a[i]));
minTmp = Math.min(a[i], Math.min(maxCur * a[i], minCur * a[i]));
maxCur = maxTmp;
minCur = minTmp;
result = Math.max(result, maxCur);
考试的时候我忘记了一步很关键的步骤,导致它一直wa了,一直dubug到4点终于想到了。
先贴一贴错误代码:
代码如下(示例):
#include<iostream>
using namespace std;
struct node
{
int z,m;
}q[100010];
int main()
{
int n,a[100010],c[100010];
string b[100010];
cin>>n;
for(int i=0;i<n;i++)
{
cin>>b[i];
//cout<<b[i].size()<<endl;
}
for(int i=0;i<n;i++)
{
if(b[i][0]=='-')
{
c[i]=-1;
if(b[i][3]=='-')
{
int x=0;
for(int j=4;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
//if(x%2==0)c[i]=1;
q[i].z=0;
q[i].m=x;
}
else
{
int x=0;
for(int j=3;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
//if(x%2==0)c[i]=1;
q[i].z=x;
q[i].m=0;
}
}
else
{
c[i]=1;
if(b[i][2]=='-')
{
int x=0;
for(int j=3;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
q[i].z=0;
q[i].m=x;
}
else
{
int x=0;
for(int j=2;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
q[i].z=x;
q[i].m=0;
}
}
}
//cout<<q[0].m<<" "<<q[1].m<<" "<<q[2].m<<endl;
int res=-100000;
int inf=10000000;
int sum1=0,s1=c[0];
int sum2=0,s2=c[0];
//if(q[0].z-q[0].m)res=c[0]*(q[0].z-q[0].m+inf);
/*else */
res=sum1=sum2=c[0]*(q[0].z-q[0].m+inf);
//cout<<res<<endl;
for(int i=1;i<n;i++)
{
/*if(i==1)
{
cout<<s1<<s2<<endl;
cout<<sum1<<sum2<<endl;
cout<<q[0].z-q[0].m<<endl;
cout<<max(c[i]*s1*(abs(sum1)+(q[0].z-q[0].m)),c[i]*s2*(abs(sum2)+(q[0].z-q[0].m)))<<endl;
}*/
sum1=max(max(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf));
sum2=min(min(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf));
if(sum1>0)s1=1;
else s1=-1;
if(sum2>0)s2=1;
else s2=-1;
/*
cout<<i<< " sum1:"<<sum1<<endl;
cout<<i<< " sum2:"<<sum2<<endl;
cout<<i<< " res:"<<res<<endl;*/
res=max(res,sum1);
}
//cout<<res<<endl;
if(res==0)printf("2^0");
else if(res<0)
{
int x;
x=min(res%inf,inf-res%inf);
printf("-2^%d",abs(res)-inf);
}
else
{
int x;
x=min(res%inf,inf-res%inf);
printf("2^%d",res-inf);
}
return 0;
}
后来想到了sum1会变,所以需要利用一个变量来存他之前的状态。
正确的代码:
代码如下(示例):
#include<iostream>
using namespace std;
struct node
{
int z,m;
}q[100010];
int main()
{
int n,a[100010],c[100010];
string b[100010];
cin>>n;
for(int i=0;i<n;i++)
{
cin>>b[i];
//cout<<b[i].size()<<endl;
}
for(int i=0;i<n;i++)
{
if(b[i][0]=='-')
{
c[i]=-1;
if(b[i][3]=='-')
{
int x=0;
for(int j=4;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
//if(x%2==0)c[i]=1;
q[i].z=0;
q[i].m=x;
}
else
{
int x=0;
for(int j=3;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
//if(x%2==0)c[i]=1;
q[i].z=x;
q[i].m=0;
}
}
else
{
c[i]=1;
if(b[i][2]=='-')
{
int x=0;
for(int j=3;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
q[i].z=0;
q[i].m=x;
}
else
{
int x=0;
for(int j=2;j<b[i].size();j++)
{
x=x*10+(b[i][j]-'0');
}
q[i].z=x;
q[i].m=0;
}
}
}
//cout<<q[0].m<<" "<<q[1].m<<" "<<q[2].m<<endl;
int res=-100000;
int inf=10000000;
int sum1=0,s1=c[0],sumt;
int sum2=0,s2=c[0];
//if(q[0].z-q[0].m)res=c[0]*(q[0].z-q[0].m+inf);
/*else */
sumt=res=sum1=sum2=c[0]*(q[0].z-q[0].m+inf);
//cout<<res<<endl;
for(int i=1;i<n;i++)
{
/*if(i==1)
{
cout<<s1<<s2<<endl;
cout<<sum1<<sum2<<endl;
cout<<q[i].z-q[i].m<<endl;
cout<<min(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m)))<<endl;
cout<<c[i]*(q[i].z-q[i].m+inf)<<endl;
cout<<min(min(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf))<<endl;
}*/
sum1=max(max(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf));
//cout<<min(min(c[i]*s1*(abs(sum1)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf))<<endl;
sum2=min(min(c[i]*s1*(abs(sumt)+(q[i].z-q[i].m)),c[i]*s2*(abs(sum2)+(q[i].z-q[i].m))),c[i]*(q[i].z-q[i].m+inf));
//if(i==1)cout<<sum2<<" "<<endl;
if(sum1>0)s1=1;
else s1=-1;
if(sum2>0)s2=1;
else s2=-1;
res=max(res,sum1);
/*
cout<<i<< " sum1:"<<sum1<<endl;
cout<<i<< " sum2:"<<sum2<<endl;
cout<<i<< " res:"<<res<<endl;*/
sumt=sum1;
}
//cout<<res<<endl;
if(res==0)printf("2^0");
else if(res<0)
{
int x;
x=min(res%inf,inf-res%inf);
printf("-2^%d",abs(res)-inf);
}
else
{
int x;
x=min(res%inf,inf-res%inf);
printf("2^%d",res-inf);
}
return 0;
}
总结:有时候想到思路了,感觉思路无比正确,但还是会出现一些错误导致题目ac不了。如何快速地找出这些错误我还得练习,说实话在比赛的时候真的气死了,写了好久,还是一直wa。气的我一直搞到了凌晨2点还是写不出(而且因为一些原因寝室没有空调,真的很烦躁)。直到我在地上躺了一会儿 ,冷静了下来,开始找例子来hack我的代码,终于在四点钟ac了。果然扣代码的时候还是需要一个冷静的头脑,不能急,越急越写不出来。(最终原因果然还是因为我太菜了 ┭┮﹏┭┮)