题目链接
细节都放到代码注释里面了
#include<bits/stdc++.h>
using namespace std;
#define rg register
int t;
int n;
int flag;//1--常数复杂度 2--开方复杂度
int cf;//记录开的是几次方
char c[50],a[150][105];
int len_c;
inline void mes()
{
flag=0;
cf=0;
memset(c,0,sizeof(c));
memset(a,0,sizeof(a));
len_c=0;
}
inline bool solve_1()
{
int tot1,tot2;//1--统计F 2--统计E
int tot;//查看F与E是否一一匹配
tot1=tot2=tot=0;
for(rg int i=1;i<=n;++i)//统计整个程序中F和E的数量和位置关系
{
if(a[i][0]=='F') tot1++;
if(a[i][0]=='E') tot2++;
tot=tot1-tot2;
if(tot<0) return false;//如果出现一个F匹配多个E,则编译错误
}
if(tot1!=tot2) return false;//两者数量不同当然编译错误
return true;//当两个条件都满足时,则①情况满足,即F与E数量和位置都匹配
}
inline bool solve_2()
{
/*
需要注意的是
变量命名重复只在循环镶嵌中存在
*/
bool vis[223]={0},vit[1000]={0};//vis用来存变量名 vit用来存i
for(rg int i=1;i<=n;++i)
{
if(a[i][0]=='F')
{
if(vis[(int)a[i][2]]==1)
{
//cout<<"kokodayo"<<endl;
return false;
}
else
{
vis[(int)a[i][2]]=1;
}
}
if(a[i][0]=='E')
{
for(rg int j=i-1;j>=1;--j)
{
if(a[j][0]=='F'&&vit[j]==0)//vit说明这个循环还没结束
{
vit[j]=1;
vis[(int)a[j][2]]=0;//消除这个循环的影响;
break;
}
}
}
}
return true;
}
inline bool judge_wrong()
{
if(solve_1()==0) return false;//① F 和 E 不匹配
if(solve_2()==0) return false;//②新建的变量与已经存在但未被销毁的变量重复两种情况),则输出ERR 。
return true;
}
inline bool work_1()//判断该程序是否为常数复杂度
{
/*
ps:
判断常数复杂度(F i x y) i从x开始每次++直到y
1.单个循环同时x,y皆为常数满足要求(F i 1 2)
2.单个循环无法进入满足要求 (F i n 1)
3.单个循环x,y皆为n满足要求(F i n n) (存疑)
4.循环组每个循环皆为常数复杂度
5.循环组内在进入开方复杂度的循环之前已经结束
eg(5)
F a 1 8
F b n 3
F c 1 n
需要注意的是循环中n到n并不会直接结束,而是会循环一次,只有在x>y的时候该循环会直接结束,x=y时会循环一次,x<y时会循环y-x+1次
所以F i n n 视为常数复杂度的循环
*/
int tot1,tot2;//1--F的数量 2--E的数量
int tot;//==tot1-tot2
bool flag;//0--当前为单循环 1--为循环组
tot1=tot2=tot=flag=0;
for(rg int i=1;i<=n;++i)
{
if(a[i][0]=='F') ++tot1;
if(a[i][0]=='E') ++tot2;
tot=tot1-tot2;
if(tot==0&&tot1==1)//单循环
{
int k=4,ans1=0;
if(a[i-1][k]!='n')
{
while(a[i-1][k]!=' ')
{
ans1*=10;
ans1+=(int)(a[i-1][k]-48);
++k;
}
++k;
if(a[i-1][k]!='n')
{
tot1=tot2=tot=0;
continue;
}
else if(a[i-1][k]=='n') return false;
}
if(a[i-1][4]=='n')//2,3. 只要第一个为n 都满足
{
tot1=tot2=0;
continue;
}
return false;//单循环只有 1,2,3满足常数复杂度 如果前两个if 都不满足 则说明该方程不是常数复杂度 直接return false
}
if(tot==0&&tot1>1)//多循环
{
for(rg int j=i-tot1*2+1;j<=i-tot1;++j)//此处为从多循环第一个循环到最后一个循环的枚举
{
if(a[j][4]=='n'&&a[j][6]!='n')
{
tot1=tot2=tot=0;
break;//此时 x>y 整个循环组提前结束
}
if(a[j][4]=='n'&&a[j][6]=='n') continue;//此时这个循环只循环一次
if(a[j][4]!='n'&&a[j][6]=='n') return false;//此时这个循环已经是开方复杂度 return false
int k=4,ans1=0;
while(a[j][k]!=' ')
{
ans1*=10;
ans1+=(int)(a[j][k]-48);
++k;
}
++k;
int ans2=0;
while(a[j][k]<='9'&&a[j][k]>='0')
{
ans2*=10;
ans2+=(int)(a[j][k]-48);
++k;
}
// cout<<a[j][k-1]<<endl;
// cout<<ans1<<" "<<ans2<<" "<<k<<endl;
if(ans1>ans2)
{
tot1=tot2=tot=0;
break;//此时这个循环组提前结束
}
if(ans1==ans2) continue;//此时这个循环只循环一次
if(ans1<ans2) continue;//此时这个循环是常数复杂度要进入下一个循环
}
tot1=tot2=tot=0;
}
}
return true;
}
inline bool work_2()//判断该程序是否为开方复杂度
{
/*
判断是否为开方复杂度
两种情况分别讨论
一.为单循环
1.只需要满足 y=n 且x!=n 就行了
二.为循环组
1.至少有一个循环满足y=n 且x!=n
2.在达到该循环之前整个循环组不能结束
即之前某个循环不能出现x>y的情况
*/
int tot1,tot2;//1--F的数量 2--E的数量
int tot;//==tot1-tot2
int cnt1,cnt2;//统计当前是几次方 cnt1统计单循环 cnt2统计循环组
tot1=tot2=tot=cnt1=cnt2=0;
for(rg int i=1;i<=n;++i)
{
if(a[i][0]=='F') ++tot1;
if(a[i][0]=='E') ++tot2;
tot=tot1-tot2;
if(tot==0&&tot1==1)//单循环
{
int k=4,ans1=0;
if(a[i-1][k]!='n')
{
while(a[i-1][k]!=' ')
{
ans1*=10;
ans1+=(int)(a[i-1][k]-48);
++k;
}
++k;
if(a[i-1][k]=='n')
{
tot1=tot2=tot=0;
cnt1=1;
continue;
}
}
if(a[i-1][4]!='n'&&a[i-1][6]=='n')//满足条件一
{
tot1=tot2=tot=0;
cnt1=1;
continue;
}
if(a[i-1][4]=='n') return false;//当x=n 时,该单循环无论如何也不可能为开方级别复杂度
tot1=tot2=tot=0;
}
if(tot==0&&tot1>1)//多循环
{
int nt;//负责找到该多循环最多为几次方
nt=0;
for(rg int j=i-tot1*2+1;j<=i-tot1;++j)//此处为从多循环第一个循环到最后一个循环的枚举
{
if(a[j][4]=='n'&&a[j][6]!='n')//循环提前结束
{
tot1=tot2=tot=0;
cnt2=max(cnt2,nt);//更新几次方
break;
}
if(a[j][4]=='n'&&a[j][6]=='n') continue;
int k=4,ans1=0;
while(a[j][k]!=' ')
{
ans1*=10;
ans1+=(int)(a[j][k]-48);
++k;
}
++k;
if(a[j][k]=='n')
{
++nt;
cnt2=max(cnt2,nt);
continue;
}
int ans2=0;
while(a[j][k]<='9'&&a[j][k]>='0')
{
ans2*=10;
ans2+=(int)(a[j][k]-48);
++k;
}
if(ans1>ans2)
{
tot1=tot2=tot=0;
cnt2=max(cnt2,nt);//更新几次方
break;//此时这个循环组提前结束
}
}
tot1=tot2=tot=0;
}
}
cnt2=max(cnt2,cnt1);
if(cnt2!=cf) return false;
return true;
}
int main()
{
cin>>t;
while(t--)
{
mes();//清空
cin>>n;//程序行数
cin>>c;
len_c=strlen(c);
for(rg int i=0;i<len_c;++i)
{
if(c[i]=='(')
{
if(c[i+1]=='1')
{
flag=1;//常数复杂度
break;
}
if(c[i+1]=='n')
{
flag=2;
int k=i+3;
while(c[k]>='0'&&c[k]<='9')
{
cf*=10;
cf+=(int)(c[k]-48);
++k;
}
break;
}
}
}
char l=getchar();//读掉第一个换行
for(rg int i=1;i<=n;++i)
{
cin.get(a[i],101);
l=getchar();//读掉每个换行符
}
if(judge_wrong()==0)//判断是否存在语法错误
{//如果有则直接输出
cout<<"ERR"<<endl;
continue;
}
if(flag==1) //如果为常数复杂度
{
if(work_1()==0) cout<<"No"<<endl;
else cout<<"Yes"<<endl;
}
else// 如果为开方复杂度
{
if(work_2()==0) cout<<"No"<<endl;
else cout<<"Yes"<<endl;
}
}
}
京公网安备 11010502036488号