20201102gryz模擬賽解題報告

簡述個人苦逼作題經歷

考的是NOIP2017day1原題,html

開始看到小凱的疑惑時感受特水,由於這題初中老師講過,node

很nice的秒切ios

T2發現是個大模擬,雖然字符串不太會用,但起碼題意很好理解數組

邊打代碼邊敲註釋,差點變量名不夠用ide

就這樣一個半小時過去了,手捏的樣例也過了spa

覺得100pts,就放了過去看T3設計

T3考的是最短路計數,想了想之前好像沒有寫過這類題,3d

硬着頭皮寫了個dfs暴力統計道路數,爲防止跑不出來還加了個計數器特判code

指望能在無0環樣例中騙點分,htm

後來在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

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
相關文章
相關標籤/搜索