20201102gryz模拟赛解题报告

简述我的苦逼做题经历

考的是NOIP2017day1原题,

开始看到小凯的疑惑时感觉特水,因为这题初中老师讲过,

很nice的秒切

T2发现是个大模拟,虽然字符串不太会用,但起码题意很好理解

边打代码边敲注释,差点变量名不够用

就这样一个半小时过去了,手捏的样例也过了

以为100pts,就放了过去看T3

T3考的是最短路计数,想了想以前好像没有写过这类题,

硬着头皮写了个dfs暴力统计道路数,为防止跑不出来还加了个计数器特判

期望能在无0环样例中骗点分,

后来在luogu上全WA了

T1 小凯的疑惑

运用了小学奥数的芝士

(赛后听说有根据昨天T2做法骗了60分的,但那个必会MLE,不过在考场上可以用来打表找规律)

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 long long a, b;//十年OI一场空,不开long long见祖宗
 5 int main()
 6 {
 7     //freopen("math.in","r",stdin);
 8     //freopen("math.out","w",stdout);
 9     cin>>a>>b;
10     cout<<(a*b-a-b)<<endl;
11     return 0;
12 }
View Code

T2 时间复杂度

这虽然是个大模拟,但坑点太多了啊

发现给出的程序格式单一,那么直接用cin单独接收就好

用flag标记小明给出的复杂度中有无n,用cst和fcst分别接收常数级的复杂度和指数级的复杂度(后来发现cst只可能是1

为了区分fsct是1的情况,把cst赋成-1

接着读入每个串,把F,和E两种情况分开处理

单独开个char数组存变量的名字,读一个F就加一个,读一个E就减一个(注意加之前先判断有没有重复的

接收起始量和终止量

开两个标记标记是否是n,开两个int记录两个量的大小

开个xh记录循环到的第几层

如果前后都是n,不作处理

考虑到有的循环能直接退出,开个spl标记

开一个栈存储有n的循环层的层数

如果前面只有前面是n,或者前面大于后面并且spl == 0 时间复杂度与top取最大值,并用spl记录此时层数

如果只有后面是n,向栈里加一个元素,大小为此时的层数,时间复杂度与top取最大值

如果层数小于栈顶的层数,就将其弹出

如果有层数小于0或者变量名重复的情况打个标记最后输出REE即可

在E操作中,如果层数小于spl,要记得归0

详细过程看代码

  1 //T2不会是个大模拟吧 
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<string>
  6 #include<cmath>
  7 using namespace std;
  8 int T, n, cnt, Otime, xh, xh2;//cnt变量名计数 
  9 int cst, fcst;//cst:常数级,fcst:指数级 
 10 bool err = 0, flag;//标记复杂度是指数级还是常数级 
 11 char blm[110];//存变量名 
 12 string s1, s2; //读入的程序 
 13 int spl;//一个特殊标记,标记外层循环o1,内层循环on^m的情况 
 14 int stk[110], top = 0;
 15 
 16 void worke(){
 17     cnt--; xh--;
 18     if(xh <= spl) spl = 0;
 19     if(xh < 0) err = 1;
 20     if(xh < stk[top]) top--;
 21     return ;
 22 }
 23 
 24 void workf(){
 25     bool str_n = 0, ed_n = 0;//标记起始点是否为n,标记终止点是否为n ;
 26     int str = 0, ed = 0;
 27     string bl, qsl, zzl;//变量, 起始量, 终止量
 28     cin>>bl>>qsl>>zzl;
 29     xh++;//循环层数加一 
 30     for(int i = 1; i <= cnt; ++i)  
 31         if(blm[i] == bl[0]) {
 32             err = 1; return ;        
 33         } 
 34     //存变量 
 35     //处理起始点 
 36     if(qsl[0] == 'n') str_n = true;
 37     else {
 38         for(int i = 0; i < qsl.size(); ++i){
 39             str = str * 10 + qsl[i] - '0';
 40         }
 41     }
 42     //处理终止点 
 43     if(zzl[0] == 'n') ed_n = true; 
 44     else {
 45         for(int i = 0; i < zzl.size(); ++i){
 46             ed = ed * 10 + zzl[i] - '0';
 47         }
 48     }
 49     if(str_n && ed_n) return ; 
 50     blm[++cnt] = bl[0];
 51     
 52     if(((str_n && !ed_n) || (!str_n && !ed_n && str > ed)) && !spl) Otime = max(Otime, top), spl = xh;
 53     if(!str_n && ed_n && !spl) {
 54         stk[++top] = xh;
 55         Otime = max(Otime, top);        
 56     }
 57     if(xh < stk[top]) top--;
 58     return ;
 59 }
 60 
 61 int main()
 62 {
 63     //freopen("complexity.in","r",stdin);
 64     //freopen("complexity.out","w",stdout);
 65     scanf("%d", &T);
 66     while(T--){
 67         scanf("%d", &n);
 68         cnt = cst = fcst = xh = xh2 = top = 0;
 69         flag = 0, err = 0;
 70         Otime = -1;
 71         cin>>s1;
 72 //        cout<<n<<"zsf"<<endl;
 73         int len = s1.size();
 74         for(int i = 0; i < len; ++i){
 75             if(s1[i] == 'n'){
 76                 flag = true;
 77             }
 78             if(s1[i] >= '0' && s1[i] <= '9'){//记录复杂度 
 79                 if(flag) fcst = fcst * 10 + s1[i] - '0';
 80                 else cst = -1;
 81             }
 82         }
 83         for(int i = 1; i <= n; ++i){
 84             cin>>s2;
 85             if(s2[0] == 'F') workf();
 86             else worke();
 87 //            cout<<spl<<"zsf"<<xh<<" "<<top<<endl;
 88         }
 89         if(err || xh) printf("ERR\n");
 90         else{
 91             if(!flag){
 92                 if(Otime == cst) printf("Yes\n");
 93                 else printf("No\n");
 94             }
 95             else{
 96                 if(Otime == fcst) printf("Yes\n");
 97                 else printf("No\n");
 98             }
 99         }
100 //        cout<<"lkp"<<Otime<<" "<<cst<<" "<<fcst<<endl;
101     }
102     return 0;
103 }
View Code

增加一份比较友善的代码,原来那份太丑了

 1 /*
 2 Work by: Suzt_ilymics
 3 Knowledge: ??
 4 Time: O(??)
 5 */
 6 #include<iostream>
 7 #include<cstdio>
 8 #include<cstring>
 9 #include<algorithm>
10 #include<cmath>
11 #include<queue>
12 #include<string>
13 #define LL long long
14 #define orz cout<<"lkp AK IOI!"<<endl
15 
16 using namespace std;
17 const int MAXN = 1e5+5;
18 const int INF = 1e9+7;
19 const int mod = 1e9+7;
20 
21 char s[100], fr[100], to[100];
22 int T, L, kans, ans;
23 int stc[MAXN], sc = 0, zimu[MAXN];
24 bool vis[MAXN]; 
25 
26 int read(){
27     int s = 0, f = 0;
28     char ch = getchar();
29     while(!isdigit(ch))  f |= (ch == '-'), ch = getchar();
30     while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
31     return f ? -s : s;
32 }
33 
34 int main()
35 {
36     T = read();
37     while(T--) {
38         sc = 0; kans = 0, ans = 0;
39         memset(vis, false, sizeof vis);
40         L = read();
41         cin >> s + 1;
42         if(s[3] == '1') kans = 0;
43         else {
44             int len = strlen(s + 1);
45             for(int i = 1; i <= len; ++i) 
46                 if(s[i] >= '0' && s[i] <= '9') 
47                     kans = kans * 10 + s[i] - '0';
48         }
49         bool Flag = false;
50         for(int i = 1; i <= L; ++i) {
51             char opt; cin >> opt;
52             if(opt == 'F') {
53                 ++sc;
54                 char g; // 变量名 
55                 cin >> g;
56                 if(vis[g]) Flag = true;
57                 vis[g] = true;
58                 zimu[sc] = g;
59                 cin >> fr + 1 >> to + 1;
60                 if(fr[1] == 'n') {
61                     if(to[1] == 'n') stc[sc] = 0;
62                     else stc[sc] = 2;
63                 } else { // fr 是常数,只需要判断 to 是否为 n 
64                     if(to[1] == 'n') stc[sc] = 1; //  
65                     else {
66                         int len1 = strlen(fr + 1), len2 = strlen(to + 1);
67                         int sum1 = 0, sum2 = 0;
68                         for(int j = 1; j <= len1; ++j) sum1 = sum1 * 10 + fr[j] - '0';
69                         for(int j = 1; j <= len2; ++j) sum2 = sum2 * 10 + to[j] - '0'; 
70                         if(sum1 > sum2) stc[sc] = 2;
71                         else stc[sc] = 0;
72                     }
73                 }
74             } else {
75                 vis[zimu[sc]] = false;
76                 --sc;
77                 if(sc < 0) Flag = true;
78             }
79             int cnt = 0;
80             for(int j = 1; j <= sc; ++j) {
81                 if(stc[j] == 2) break;
82                 cnt += stc[j];
83             }
84             ans = max(ans, cnt);
85         }
86         if(sc) Flag = true;
87         if(Flag) puts("ERR");
88         else if(ans == kans) puts("Yes");
89         else puts("No");
90     }
91     return 0; 
92 }

 

 

T3 逛公园

关键是0环的问题不太好处理,但正解好像设计到一点dp,0环直接被过滤掉了

https://www.cnblogs.com/wxyww/p/noip2017Day1T3.html#643448942

这个博客讲的挺好的

题解是SPFA,我用的dij做的(题目中只有0环,嘿嘿,能卡过去)

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<queue>
  4 #include<cstring>
  5 using namespace std;
  6 const int MAXN = 1e5+5;
  7 const int MAXM = 2e5+5;
  8 struct edge{
  9     int to, w, nxt;
 10 }e[MAXM], e2[MAXM];
 11 struct node{
 12     int point, dis;
 13     bool operator < (const node &b) const {return dis > b.dis; }
 14 };
 15 int head[MAXN], num_edge, head2[MAXN], num_edge2;
 16 int T, n, m, k ,p, lim, cnt, ans;
 17 int dis[MAXN], num[MAXN];
 18 bool vis[MAXN];
 19 priority_queue<node> q;
 20 
 21 int read(){
 22     int s = 0, w = 1;
 23     char ch = getchar();
 24     while(ch < '0' || ch > '9') {if(ch == '-') w = -1; ch = getchar(); }
 25     while(ch >= '0' && ch <= '9') s = (s << 1) + (s << 3) + ch - '0', ch = getchar();
 26     return s * w;
 27 }
 28 
 29 void add(int from, int to, int w){
 30     e[++num_edge].to = to;
 31     e[num_edge].w = w;
 32     e[num_edge].nxt = head[from];
 33     head[from] = num_edge;
 34 }
 35 
 36 void add2(int from, int to, int w){
 37     e2[++num_edge2].to = to;
 38     e2[num_edge2].w = w;
 39     e2[num_edge2].nxt = head2[from];
 40     head2[from] = num_edge2;
 41 }
 42 
 43 
 44 void dij(){
 45     memset(dis, 0x3f, sizeof(dis));
 46     memset(vis, 0, sizeof(vis));
 47     dis[n] = 0;
 48     q.push((node){n, 0});
 49     while(!q.empty()){
 50         node t = q.top(); q.pop();
 51         int u = t.point;
 52         vis[u] = 1;
 53         for(int i = head2[u]; i; i = e2[i].nxt){
 54             int v = e2[i].to;
 55             if(dis[v] > dis[u] + e2[i].w){
 56                 dis[v] = dis[u] + e2[i].w;
 57                 if(!vis[v]) q.push((node){v, dis[v]});
 58             }
 59         }
 60     }
 61 }
 62 
 63 int bz[MAXN][60], f[MAXN][60];
 64 int dfs(int x, int lim){
 65     if(bz[x][lim] == 2) return f[x][lim];
 66     if(bz[x][lim] == 1) return -1;
 67     bz[x][lim] = 1;
 68     for(int i = head[x]; i; i = e[i].nxt){
 69         int v = e[i].to;
 70         int w = lim - (dis[v] + e[i].w - dis[x]);
 71         if(w < 0 || w > k) continue;
 72         int ans = dfs(v, w);
 73         if(ans == -1) return -1;
 74         f[x][lim] += ans;
 75         f[x][lim] %= p;
 76     }
 77     bz[x][lim] = 2;
 78     return f[x][lim];
 79 }
 80 
 81 int main()
 82 {
 83     //freopen("park.in","r",stdin);
 84     //freopen("park.out","w",stdout);
 85     T = read();
 86     while(T--){
 87         memset(head, 0, sizeof(head));
 88         memset(head2, 0, sizeof(head2));
 89         memset(f, 0, sizeof(f));
 90         memset(bz, 0, sizeof(bz));
 91         num_edge = num_edge2 = cnt = 0;
 92         n = read(), m = read(), k = read(), p = read();
 93         for(int i = 1, u, v, w; i <= m; ++i){
 94             u = read(), v = read(), w = read();
 95             add(u, v, w);
 96             add2(v, u, w);
 97         }
 98         dij();
 99         f[n][0] = 1;
100         for(int i = 0; i <= k; ++i){
101             int kkk = dfs(1, i);
102             if(kkk == -1){
103                 cnt = -1; break;
104             }
105             cnt += kkk;
106             cnt %= p;
107         }
108         printf("%d\n", cnt);
109     }
110     return 0;
111  } 
View Code

 

posted @ 2020-11-02 17:29  Suzt_ilymtics  阅读(114)  评论(0编辑  收藏  举报