zoukankan      html  css  js  c++  java
  • 【洛谷5698】[CTSC1998] 算法复杂度(又是被模拟吊打的一天)

    点此看题面

    • 给定一个程序,包含下列语句:

      • begin:开始程序。
      • loop x:开始一个(x)次的循环,其中(x)为正整数或(n)
      • op x:执行(x)个单位的操作,其中(x)为正整数或(n)
      • break:直接退出循环。
      • continue:跳过这次循环的剩余语句,直接进入下一次循环。
      • end:结束程序/循环。
    • 求一个多项式(不能忽略常数项和系数),表示最终复杂度。

    • 循环层数(le20),最终系数(le10^9)

    此题数据出锅

    尽管题目中保证了(x)为正整数或(n),然而数据中依然出现了(x=0)的情况。。。

    为了通过此题,必须特判一下,如果loop x操作中(x=0),将其视作(x=n)

    纯粹模拟

    显然这种东西是要对每层循环开栈进行模拟的,对此考虑开一堆奇奇怪怪的数组:

    • (S[x],P[x]):分别表示进入第(x)层循环所有系数之积以及(n)的次数
    • (G[x]):表示第(x)层循环的循环次数x(可以用(G[x]=0)表示(n))。
    • (C[x][y]):记录第(x)层循环(y)次项的系数。

    然后对于每种操作分类讨论:

    • loop:进入一个新的循环,求出(G[T]),然后据此在(S[T-1])(P[T-1])的基础上进行修正。
    • op:如果(x=n),给(C[T][P[T]+1])加上(S[T]);否则给(C[T][P[T]])加上(S[T] imes x)
    • break:相当于这个循环只执行了一次,所以消去(G[T])的贡献,然后忽视这个循环之后的语句(忽视可以用(S[T]=0)标记)。
    • continue:只要忽视这个循环之后的语句就好了。
    • end:把这个循环的贡献加到前一个循环中。

    口胡起来就是这样,具体实现还是有一些细节的,详见代码。。。

    代码:(O(20|s|))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 30
    #define LL long long
    using namespace std;
    int n,P[N+5];LL ans[N+5],G[N+5],S[N+5],C[N+5][N+5];string s; 
    int main()
    {
    	RI T=0,i;LL x;ios::sync_with_stdio(false),cin>>s,S[0]=1,P[0]=0;W(~T)
    	{
    		if(cin>>s,s=="loop")//循环
    		{
    			if(++T,S[T]=S[T-1],P[T]=P[T-1],cin>>s,s=="0"||s=="n") {G[T]=0,++P[T];continue;}//如果x=n(因数据出锅有x=0)
    			for(x=i=0;i^s.length();++i) x=x*10+(s[i]&15);G[T]=x,S[T]*=x;continue;//如果x为正整数
    		}
    		if(s=="op")//操作
    		{
    			if(cin>>s,!S[T]) continue;if(s=="n") {C[T][P[T]+1]+=S[T];continue;}//如果x=n
    			for(x=i=0;i^s.length();++i) x=x*10+(s[i]&15);C[T][P[T]]+=S[T]*x;continue;//如果x为正整数
    		}
    		if(s=="break")//退出循环
    		{
    			if(!T||!S[T]) continue;if(!G[T]) for(i=0;i<=N;++i) C[T][i]=C[T][i+1];//如果G[T]=n
    			else for(i=0;i<=N;++i) C[T][i]/=G[T];S[T]=0;continue;//如果G[T]为正整数
    		}
    		if(s=="continue") {T&&(S[T]=0);continue;}//跳过循环,直接忽视后面语句
    		if(s=="end") {for(i=0;i<=N;++i) (T?C[T-1]:ans)[i]+=C[T][i],C[T][i]=0;--T;continue;}//结束循环,把贡献归到上一层循环
    	}
    	for(x=0,i=N;~i;--i) ans[i]&&(x?(cout<<'+',0):(x=1),//输出答案
    		(!i||ans[i]^1)&&(cout<<ans[i],0),i&&(cout<<'n',i^1&&(cout<<'^'<<i,0)));//注意一些判断
    	return !x&&(cout<<'0'<<endl),0;
    }
    
  • 相关阅读:
    LeetCode 1245. Tree Diameter
    LeetCode 1152. Analyze User Website Visit Pattern
    LeetCode 1223. Dice Roll Simulation
    LeetCode 912. Sort an Array
    LeetCode 993. Cousins in Binary Tree
    LeetCode 1047. Remove All Adjacent Duplicates In String
    LeetCode 390. Elimination Game
    LeetCode 1209. Remove All Adjacent Duplicates in String II
    LeetCode 797. All Paths From Source to Target
    LeetCode 1029. Two City Scheduling
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5698.html
Copyright © 2011-2022 走看看