zoukankan      html  css  js  c++  java
  • [NOIP补坑计划]NOIP2017 题解&做题心得

    终于做完了……

    场上预计得分:?(省一分数线:295)

    由于看过部分题解所以没有预计得分qwq

    题解:

    D1T1 小凯的疑惑

    题面

    震惊!一道小学奥数题竟难倒无数高中考生!

    欢迎大家以各种姿势*和谐*出题人

    证明见这篇博客

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<queue>
     7 #include<map>
     8 #define inf 2147483647
     9 #define eps 1e-9
    10 using namespace std;
    11 typedef long long ll;
    12 ll a,b;
    13 int main(){
    14     scanf("%lld%lld",&a,&b);
    15     printf("%lld",a*b-a-b);
    16     return 0;
    17 }

    D1T2 时间复杂度

    题面

    细节太多就不说了……我的代码应该是loj上最丑的

    要特别注意的几个点:

    1.不被执行的循环内可能会有语法错误;

    2.要判断x=y=n的情况;

    3.可能会开头没有F直接E;

    4.看代码吧……

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<queue>
     7 #include<stack>
     8 #include<map>
     9 #define inf 2147483647
    10 #define eps 1e-9
    11 using namespace std;
    12 typedef long long ll;
    13 int t,l,x,t1,t2,nd,las,cnt,mx,top,st[101],nam[101];
    14 char s[101];
    15 bool ch,err,run,nm[26],ntrun[101];
    16 int main(){
    17     scanf("%d",&t);
    18     while(t--){
    19         memset(nm,0,sizeof(nm));
    20         memset(nam,0,sizeof(nam));
    21         memset(ntrun,0,sizeof(ntrun));
    22         err=ch=false;
    23         run=true;
    24         mx=t1=t2=x=top=cnt=0;
    25         las=-1;
    26         scanf("%d%s",&l,s+1);
    27         for(int i=1,ii=strlen(s+1);i<=ii;i++){
    28             if(s[i]=='n')ch=true;
    29             if(isdigit(s[i]))x=x*10+s[i]-'0';
    30         }
    31         if(x==1&&!ch)nd=0;
    32         else nd=x;
    33         for(int i=1;i<=l;i++){
    34             scanf("%s",s+1);
    35             if(s[1]=='F'){
    36                 scanf("%s",s+1);
    37                 if(!nm[s[1]-'a'])nm[s[1]-'a']=true,nam[i]=s[1]-'a';
    38                 else err=true;
    39                 t1=t2=0;
    40                 scanf("%s",s+1);
    41                 if(s[1]=='n')t1=101;
    42                 else for(int i=1;i<=strlen(s+1);i++)t1=t1*10+s[i]-'0';
    43                 scanf("%s",s+1);
    44                 if(s[1]=='n')t2=101;
    45                 else for(int i=1;i<=strlen(s+1);i++)t2=t2*10+s[i]-'0';
    46                 if((t1!=101&&t2!=101&&t1>t2)||(t1==101&&t2<101)){
    47                     if(run){
    48                         run=false;
    49                         las=i;
    50                     }
    51                 }
    52                 st[++top]=i;
    53                 if(run&&t1!=t2&&t2==101)cnt++;
    54                 else ntrun[i]=true;
    55                 mx=max(mx,cnt);
    56             }else{
    57                 if(top){
    58                     if(run&&!ntrun[st[top]])cnt--;
    59                     if(st[top]==las){
    60                         las=-1;
    61                         run=true;
    62                     }
    63                     nm[nam[st[top]]]=false;
    64                     top--;
    65                 }else err=true;
    66             }
    67         }
    68         if(top)err=true;
    69         if(err)puts("ERR");
    70         else puts(mx==nd?"Yes":"No");
    71     }
    72     return 0;
    73 }

    D1T3 逛公园

    题面

    听说SPFA会被卡?吓得我写了个dij……

    显然是计数dp,设$dis[i]$表示i到终点的最短路,$f[i][k]$表示点i到终点距离小于等于$dis[i]+k$的方案数,记忆化搜索就好了……

    如果一个状态同时出现多次则说明有零环无解;

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<cmath>
     7 #include<queue>
     8 #include<stack>
     9 #include<map>
    10 #define inf 2147483647
    11 #define eps 1e-9
    12 using namespace std;
    13 typedef long long ll;
    14 typedef pair<int,int> pii;
    15 struct edge{
    16     int v,w,next;
    17 }a[500001],_a[500001];
    18 int t,n,m,k,p,u,v,w,tot=0,_tot=0,head[100001],_head[100001],f[100001][51],dis[100001];
    19 bool used[100001],ch[100001][51];
    20 void add(int u,int v,int w){
    21     a[++tot].v=v;
    22     a[tot].w=w;
    23     a[tot].next=head[u];
    24     head[u]=tot;
    25 }
    26 void _add(int u,int v,int w){
    27     _a[++_tot].v=v;
    28     _a[_tot].w=w;
    29     _a[_tot].next=_head[u];
    30     _head[u]=_tot;
    31 }
    32 void dij(int vs){
    33     priority_queue<pii,vector<pii>,greater<pii> >q;
    34     dis[vs]=0;
    35     q.push(pii(0,vs));
    36     while(!q.empty()){
    37         int u=q.top().second;
    38         q.pop();
    39         if(used[u])continue;
    40         used[u]=true;
    41         for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    42             int v=a[tmp].v;
    43             if(dis[v]>dis[u]+a[tmp].w){
    44                 dis[v]=dis[u]+a[tmp].w;
    45                 q.push(pii(dis[v],v));
    46             }
    47         }
    48     }
    49 }
    50 int work(int x,int k){
    51     if(ch[x][k])return -1;
    52     if(f[x][k])return f[x][k];
    53     ch[x][k]=true;
    54     if(x==n)f[x][k]=1;
    55     for(int tmp=_head[x];tmp!=-1;tmp=_a[tmp].next){
    56         int v=_a[tmp].v,nw=dis[v]-dis[x]+_a[tmp].w;
    57         if(nw<=k){
    58             int t=work(v,k-nw);
    59             if(t==-1)return f[x][k]=-1;
    60             f[x][k]=(f[x][k]+t)%p;
    61         }
    62     }
    63     ch[x][k]=false;
    64     return f[x][k];
    65 }
    66 int main(){
    67     scanf("%d",&t);
    68     while(t--){
    69         tot=_tot=0;
    70         memset(used,0,sizeof(used));
    71         memset(f,0,sizeof(f));
    72         memset(ch,0,sizeof(ch));
    73         memset(head,-1,sizeof(head));
    74         memset(_head,-1,sizeof(_head));
    75         memset(dis,0x3f,sizeof(dis));
    76         scanf("%d%d%d%d",&n,&m,&k,&p);
    77         for(int i=1;i<=m;i++){
    78             scanf("%d%d%d",&u,&v,&w);
    79             add(v,u,w);
    80             _add(u,v,w);
    81         }
    82         dij(n);
    83         printf("%d
    ",work(1,k)%p);
    84     }
    85     return 0;
    86 }

    D2T1 奶酪

    题面

    裸bfs水题送温暖~

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<cmath>
     7 #include<queue>
     8 #include<stack>
     9 #include<map>
    10 #define inf 2147483647
    11 #define eps 1e-9
    12 using namespace std;
    13 typedef long long ll;
    14 struct edge{
    15     ll v,next;
    16 }a[500001];
    17 ll t,n,h,r,tot=0,x[1001],y[1001],z[1001],up[1001],dn[1001],head[1001];
    18 bool ok,isin[1001];
    19 void add(ll u,ll v){
    20     a[++tot].v=v;
    21     a[tot].next=head[u];
    22     head[u]=tot;
    23 }
    24 bool bfs(){
    25     queue<ll>q;
    26     memset(isin,0,sizeof(isin));
    27     for(ll i=1;i<=n;i++){
    28         if(dn[i]){
    29             q.push(i);
    30             isin[i]=true;
    31         }
    32     }
    33     while(!q.empty()){
    34         ll u=q.front();
    35         q.pop();
    36         for(ll tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    37             ll v=a[tmp].v;
    38             if(up[v])return true;
    39             if(!isin[v]){
    40                 q.push(v);
    41                 isin[v]=true;
    42             }
    43         }
    44     }
    45     return false;
    46 }
    47 int main(){
    48     scanf("%lld",&t);
    49     while(t--){
    50         memset(head,-1,sizeof(head));
    51         memset(up,0,sizeof(up));
    52         memset(dn,0,sizeof(dn));
    53         tot=0;
    54         ok=false;
    55         scanf("%lld%lld%lld",&n,&h,&r);
    56         for(ll i=1;i<=n;i++){
    57             scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
    58             if(z[i]<=r)dn[i]=true;
    59             if(z[i]>=h-r)up[i]=true;
    60             if(dn[i]&&up[i])ok=true;
    61         }
    62         if(ok){
    63             puts("Yes");
    64             continue;
    65         }
    66         for(ll i=1;i<n;i++){
    67             for(ll j=i+1;j<=n;j++){
    68                 if((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j])<=r*r*4){
    69                     add(i,j);
    70                     add(j,i);
    71                 }
    72             }
    73         }
    74         puts(bfs()?"Yes":"No");
    75     }
    76     return 0;
    77 } 

    D2T2 宝藏

    题面

    看到数据范围肯定就是搜索或者状压DP了……听说记忆化搜索可以艹过去?

    题解Orzxfz

    设$f[i][s]$表示当前深度为i,已经访问过的点的状态为s,则$f[i][s]=min{t∈s | f[i-1][t]+i*get(t,soplus t)}$,其中$get(x,y)$表示集合y中所有点都向x中连边的最小代价;

    枚举子集转移就好了,时间复杂度$O(n^23^n)$

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<cmath>
     7 #include<queue>
     8 #include<stack>
     9 #include<map>
    10 #define inf 0x7f7f7f7f
    11 #define eps 1e-9
    12 #define lb(x) (x&-x)
    13 using namespace std;
    14 typedef long long ll;
    15 ll n,m,ans=inf,u,v,w,d[15][15],f[15][10001],lg[10001];
    16 ll get(ll x,ll y){
    17     ll ret=0,tmp;
    18     for(ll i=y;i;i-=lb(i)){
    19         tmp=inf;
    20         for(ll j=x;j;j-=lb(j)){
    21             tmp=min(tmp,d[lg[lb(i)]][lg[lb(j)]]);
    22         }
    23         ret+=tmp;
    24     }
    25     return ret;
    26 }
    27 int main(){
    28     memset(d,0x7f,sizeof(d));
    29     memset(f,0x7f,sizeof(f));
    30     for(int i=0;i<=12;i++)lg[1<<i]=i;
    31     scanf("%lld%lld",&n,&m);
    32     for(ll i=1;i<=m;i++){
    33         scanf("%lld%lld%lld",&u,&v,&w);
    34         u--,v--;
    35         d[v][u]=d[u][v]=min(d[u][v],w);
    36     }
    37     if(n==1)return puts("0"),0;
    38     for(ll i=0;i<n;i++){
    39         f[0][1<<i]=0;
    40     }
    41     for(ll i=1;i<n;i++){
    42         for(ll s=1;s<(1<<n);s++){
    43             for(ll t=s;t;t=s&(t-1)){
    44                 f[i][s]=min(f[i][s],f[i-1][t]+i*get(t,s^t));
    45             }
    46         }
    47     }
    48     for(ll i=0;i<n;i++){
    49         ans=min(ans,f[i][(1<<n)-1]);
    50     }
    51     printf("%lld",ans);
    52     return 0;
    53 }

    D2T3 列队

    题面

    这题标志着log级数据结构正式进入noip!(orzlxl)

    splay的做法很明显……但是不好写并且€€£老爷机会卡常……

    正解是对每一行和最后一列开一个线段树,每次$(x,y)$出队就找到第x行找到第y个未被使用的值(类似第k大),再从最后一列的那个线段树中找到第x个值放到第x行末尾,最后把开始找到的那个值放到最后一列末尾即可;

    注意$y=m$时要特判,线段树要动态开点;

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<cmath>
     7 #include<queue>
     8 #include<stack>
     9 #include<map>
    10 #define inf 0x7f7f7f7f
    11 #define eps 1e-9
    12 #define lb(x) (x&-x)
    13 #define N 800000
    14 using namespace std;
    15 typedef long long ll;
    16 struct node{
    17     ll v;
    18     int ls,rs;
    19 }t[10000001];
    20 int n,m,q,x,y,cnt=0,rts[600001];
    21 vector<ll>v[600001];
    22 void updata(int l,int r,int &u,int p){
    23     if(!u)u=++cnt;
    24     t[u].v++;
    25     if(l==r)return;
    26     int mid=(l+r)/2;
    27     if(p<=mid)updata(l,mid,t[u].ls,p);
    28     else updata(mid+1,r,t[u].rs,p);
    29 }
    30 int query(int l,int r,int u,int k){
    31     if(l==r){
    32         return l;
    33     }
    34     int mid=(l+r)/2,tmp=mid-l+1-t[t[u].ls].v;
    35     if(tmp>=k)return query(l,mid,t[u].ls,k);
    36     else return query(mid+1,r,t[u].rs,k-tmp);
    37 }
    38 ll del1(int p,ll x){
    39     ll ret;
    40     int nw=query(1,N,rts[n+1],p);
    41     updata(1,N,rts[n+1],nw);
    42     if(nw<=n)ret=(ll)nw*m;
    43     else ret=v[n+1][nw-n-1];
    44     if(x)v[n+1].push_back(x);
    45     else v[n+1].push_back(ret);
    46     return ret;
    47 }
    48 ll del2(int p,int x){
    49     ll ret;
    50     int nw=query(1,N,rts[p],x);
    51     updata(1,N,rts[p],nw);
    52     if(nw<m)ret=(ll)(p-1)*m+nw;
    53     else ret=v[p][nw-m];
    54     v[p].push_back(del1(p,ret));
    55     return ret;
    56 }
    57 int main(){
    58     scanf("%d%d%d",&n,&m,&q);
    59     for(int i=1;i<=q;i++){
    60         scanf("%d%d",&x,&y);
    61         printf("%lld
    ",y==m?del1(x,0):del2(x,y));
    62     }
    63     return 0;
    64 }

    总结:

    感觉14~17年难度在递增……这个D2T2和D2T3都好神仙啊qwq

    NOIP2018 加油!!!!!

  • 相关阅读:
    5.scala中的对象
    4.scala中的类
    第八章 前端框架
    第六章 用户管理
    第五章 权限验证
    第四章 功能初始化
    第三章 项目结构
    第二章 基于二进制进行权限管理的理论知识
    第一章 权限管理DEMO简介
    NopCommerce源代码分析之用户验证和权限管理
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/9934904.html
Copyright © 2011-2022 走看看