NOIP(第18届)--2012--提高组--复赛--试题与答案(NA18)

2022-07-05 已有0人阅读 作者: IT航班

中小学编程红宝书.zip

 


第1题(day1):Vigenere密码

1、说明

A、试题类型:

       密码问题。

 

B、算法模型:

       读题。

 

C、试题说明:

       用密文降去密钥,注意一下减后的数如果小于’a’或’A’要加26。

2、代码

#include<iostream>

#include<cstdio>

#include<algorithm>

#include<cstring>

#include<cmath>

using namespace std;

 

int l1,l2;

char a[1001],b[1001];

 

int main()

{

       cin>>a;

       cin>>b;

       l1=strlen(a);

       l2=strlen(b);

       for (int i=0;i<l2;i++)

       {

              int c=a[i%l1],n=0;

              if (c>='a'&&c<='z')     n=c-'a';

              else n=c-'A';

              if (b[i]>='a' && b[i]<='z')

              {

                     if (b[i]-n<'a') b[i]=b[i]+26-n;

                     else b[i]-=n;

              }

              else

              {

                     if (b[i]-n<'A') b[i]=b[i]+26-n;

                     else b[i]-=n;

              }

       }

       cout<<b<<endl;

       return 0;

}

第2题(day1):国王游戏

1、说明

A、试题类型:

       算法问题。

 

B、算法模型:

       贪心(排序)。

 

C、试题说明:

       注意高精度。

2、代码

#include<cstdio>

#include<algorithm>

using namespace std;

 

const int maxn=1010,maxlen=5000;

struct cyc{int a,b,c;}a[maxn];

int n,lens,x,lmax,lena;

int sum[maxlen],ans[maxlen],maxs[maxlen];

 

bool cmp(cyc a,cyc b)

{

       return a.c<b.c;

}

 

void cheng(int numi)

{

    int num=a[numi].a;x=0;

    for(int i=1;i<=lens;i++)

       {

              x+=sum[i]*num;

              sum[i]=x%10;

              x/=10;

       }

 

    while(x>0)

              sum[++lens]=x%10,x/=10;

       //    printf("1...%d * lens=%d\n",numi,lens);

       //    for(int i=1;i<=lens;i++)printf("%d",sum[i]);printf("\n");

}

 

void divs(int numi)

{

    int num=a[numi].b;x=0;

      

    for(int i=lens;i>=1;i--)

       {

              x=x*10+sum[i];

              ans[i]=x/num;

              x%=num;

       }

 

    lena=lens;

    while(ans[lena]==0&&lena>1)lena--;

       //    printf("1...%d-1/%d / lens=%d\n",numi,numi,lena);

       //    for(int i=1;i<=lena;i++)printf("%d",ans[i]);printf("\n");

 

    bool f=1;

    if(lena>lmax)f=0;else if(lena<lmax)f=1;else

              for(int i=lena;i>=1;i--)

                     if(ans[i]>maxs[i]){f=0;break;}else if(ans[i]<maxs[i]){f=1;break;}

                     if(!f)

                     {

                            for(int i=1;i<=lena;i++)maxs[i]=ans[i];

                            lmax=lena;

                     }

}

 

int main()

{

    scanf("%d",&n);

    for(int i=1;i<=n+1;i++)

              scanf("%d%d",&a[i].a,&a[i].b),a[i].c=a[i].a*a[i].b;

      

    sort(a+2,a+n+2,cmp);

       //for(int i=1;i<=n+1;i++)printf("%d %d\n",a[i].a,a[i].b);

      

    sum[(lens=1)]=1;

       cheng(1);

       maxs[(lmax=1)]=0;

    for(int i=2;i<=n+1;i++)

              divs(i),cheng(i);

    for(int i=lmax;i>=1;i--)

              printf("%d",maxs[i]);

      

    return 0;

}

第3题(day1):开车旅行

1、说明

A、试题类型:

       生活应用。

 

B、算法模型:

       双向链表。

 

C、试题说明:

       无。

 

2、代码

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

 

typedef long long lol;

 

struct Node

{

       int L,R,id;

       lol  h;

}a[100001];

 

lol A[100001][19],B[100001][19];

int f[100001][19];

int n,pos[100001],First[100001],Second[100001],m;

lol h[100001],suma,sumb,x0;

double ans=2e9;

int ansnum;

 

bool cnmp(Node a,Node b)

{

       return a.h<b.h;

}

 

int work(int p,int x,int y)

{

       if (x==-1&&y==-1)

              return -1;

       else if (x==-1)

              return a[y].id;

       else if (y==-1)

              return a[x].id;

       else

    {

              if (a[p].h-a[x].h>a[y].h-a[p].h)

                     return a[y].id;

              else return

                     a[x].id;

    }

}

 

void Init_order()

{

       int i;

       sort(a+1,a+n+1,cnmp);

       for (i=1;i<=n;i++)

       {

              pos[a[i].id]=i;

              a[i].R=i+1;

              a[i].L=i-1;

       }

      

       a[1].L=-1;

       a[n].R=-1;

      

       for (i=1;i<=n;i++)

       {

              int x=pos[i];

              First[i]=work(x,a[x].L,a[x].R);

              if (First[i]==-1)

                     Second[i]=-1;

              else

                     if (First[i]==a[a[x].L].id) Second[i]=work(x,a[a[x].L].L,a[x].R);

                     else Second[i]=work(x,a[x].L,a[a[x].R].R);

                     int z=a[x].L;a[a[x].L].R=a[x].R;a[a[x].R].L=z;

       }

}

 

long long absx(long long x)

{

       if (x>0)

              return x;

       else

              return -x;

}

 

int main()

{

       int i,j,x;

       long long x1;

       // freopen("car.in","r",stdin);

       // freopen("car.out","w",stdout);

       cin>>n;

      

       for (i=1;i<=n;i++)

       {

              scanf("%lld",&a[i].h);

              h[i]=a[i].h;

              a[i].id=i;

       }

      

       Init_order();

       for (i=1;i<=n;i++)

              if (Second[i]!=-1)

              {

                     if (First[Second[i]]!=-1)

                     {

                            f[i][0]=First[Second[i]];

                            A[i][0]=absx(h[Second[i]]-h[i]);

                            B[i][0]=absx(h[First[Second[i]]]-h[Second[i]]);

                     }

                     else A[i][0]=absx(h[Second[i]]-h[i]);

                     // cout<<'x'<<A[i][0]<<' '<<B[i][0]<<endl;

              }

             

              for (j=1;j<=17;j++)

              {

                     for (i=1;i<=n;i++)

                     {

                            if (f[i][j-1])

                                   f[i][j]=f[f[i][j-1]][j-1];

                            A[i][j]=A[i][j-1];

                            if (f[i][j-1])

                                   A[i][j]+=A[f[i][j-1]][j-1];

                            B[i][j]=B[i][j-1];

                            if (f[i][j-1])

                                   B[i][j]+=B[f[i][j-1]][j-1];

                            // cout<<A[i][j]<<' '<<B[i][j]<<endl;

                     }

              }

             

              cin>>x0;

             

              for (i=1;i<=n;i++)

              {

                     int x=i;

                     long long sum=x0;

                     suma=0;sumb=0;

                     for (j=17;j>=0;j--)

                            if (f[x][j]&&A[x][j]+B[x][j]<=sum)

                            {

                                   sum-=A[x][j]+B[x][j];

                                   suma+=A[x][j];

                                   sumb+=B[x][j];

                                   x=f[x][j];

                            }

                           

                            if (A[x][0]!=0&&A[x][0]<=sum)

                            {

                                   suma+=A[x][0];

                            }

                            // cout<<suma<<' '<<sumb<<endl;

                            if (sumb==0)

                                   continue;

                            if (suma==0)

                                   continue;

                            if ((double)suma/sumb<ans)

                            {

                                   ansnum=i;

                                   ans=(double)suma/sumb;

                            }

                            else if ((double)suma/sumb==ans&&h[ansnum]<h[i])

                            {

                                   ansnum=i;

                            }

              }

 

              cout<<ansnum<<endl;

              cin>>m;

 

              for (i=1;i<=m;i++)

              {

                     scanf("%d%lld",&x,&x1);

                     long long sum=x1;

                     suma=0;sumb=0;

                     for (j=17;j>=0;j--)

                            if (f[x][j]>0&&A[x][j]+B[x][j]<=sum)

                            {

                                   sum-=A[x][j]+B[x][j];

                                   suma+=A[x][j];

                                   sumb+=B[x][j];

                                   x=f[x][j];

                            }

                            if (A[x][0]!=0&&A[x][0]<=sum)

                            {

                                   suma+=A[x][0];

                            }

                            printf("%lld %lld\n",suma,sumb);

              }

}

 

第1题(day2):同余方程

1、说明

A、试题类型:

       经典数学问题。

 

B、算法模型:

       扩展欧几里得。

 

C、试题说明:

       最小正整数求解,求出来 x 要模一次 b,然后加上 b 再模一次。

 

 

2、代码

#include <cstdio>

 

void exgcd(int a, int b, int g, int &x, int &y)

{

    if (b == 0)

       {

        x = 1, y = 0;

        g = a;

    }

       else

       {

        exgcd(b, a % b, g, y, x);

        y -= x * (a / b);

    }

}

 

int main()

{

    int a, b, g, x, y;

    scanf("%d %d", &a, &b);

    exgcd(a, b, g, x, y);

    x = ((x % b) + b) % b;

    printf("%d\n", x);

      

    return 0;

}

第2题(day2):借教室

1、说明

A、试题类型:

       基本数据结构。

 

B、算法模型:

    线段树操作,二分方法应用。

 

C、试题说明:

       无。

 

 

2、代码

#include<iostream>

#include<cstdio>

#include<cstring>

using namespace std;

 

int n,m,ans,a[1000010],d[1000010],x[1000010],y[1000010],s[1000010],sum;

 

template <class T> T get(T &u)

{

       char x;for(;!isdigit(x=getchar()););

       for(u=x-48;isdigit(x=getchar());u*=10,u+=(x-48));

       ungetc(x,stdin);return u;

}

 

bool judge(int v)

{

       memset(s,0,sizeof(s));

       sum=0;

 

       for(int i=1;i<=v;i++)

       {

              s[x[i]]+=d[i];

              s[y[i]+1]-=d[i];

       }

      

       for(int i=1;i<=n;i++)

       {

              sum+=s[i];

              if(sum>a[i])return 0;

    }

      

    return 1;

}

 

int main()

{

       get(n),get(m);

      

       for(int i=1;i<=n;i++)get(a[i]);

       for(int i=1;i<=m;i++)

              get(d[i]),get(x[i]),get(y[i]);

       int l=1,r=m;

      

       while(l<=r)

       {

              int mid=(l+r)>>1;

              if(!judge(mid)){ans=mid;r=mid-1;}

              else l=mid+1;

       }

      

       if(!ans)

              printf("0");

       else

              printf("-1\n%d",ans);

       return 0;

}

第3题(day2):疫情控制

1、说明

A、试题类型:

       基本算法。

 

B、算法模型:

       二分法。

 

C、试题说明:   

预处理倍增。 二分答案。

 

 

2、代码

#include<cstdio>

#include<cctype>

#include<cstring>

#include<algorithm>

using namespace std;

 

#define N 50005

#define reg register

#define ll long long

 

int n,m,head[N],cnt,p[N],dep[N],f[N][17],cnta,cntb;

ll g[N][17];

bool vis[N];

 

struct nd

{

    ll num;

    int d;

    bool operator <(const nd& rhs)const{return num<rhs.num;}

}a[N],b[N];

 

struct edge

{

    int to,dis,nxt;

}e[N<<1];

 

inline int readint()

{

    reg char c=getchar();

    for(;!isdigit(c);c=getchar());

    reg int d=0;

    for(;isdigit(c);c=getchar())

    d=(d<<3)+(d<<1)+(c^'0');

    return d;

}

 

void Dfs(int now)

{//预处理

    for(reg int i=head[now];i;i=e[i].nxt)

    if(!dep[e[i].to])

    {

        dep[e[i].to]=dep[now]+1;

        f[e[i].to][0]=now;

        g[e[i].to][0]=e[i].dis;

        Dfs(e[i].to);

    }

}

 

void feng(int now)

{

    if(vis[now])

         return;

    vis[now]=true;

    reg bool lt=true;

    for(reg int i=head[now];i;i=e[i].nxt)

    if(dep[now]<dep[e[i].to])

    {

        lt=false;

        feng(e[i].to);

        vis[now]&=vis[e[i].to];

    }

 

    if(lt)

         vis[now]=false;

}

 

bool ok(ll k)

{//判断

    reg int x;

    reg ll sum;

    cnta=cntb=0;

    memset(vis,0,sizeof vis);

    memset(a,0,sizeof a);

    memset(b,0,sizeof b);

 

    for(reg int i=1;i<=m;++i)

    {

        x=p[i],sum=0;

        for(reg int j=16;j>-1;--j)//让军队爬上来

        if(f[x][j]>1&&sum+g[x][j]<=k)

        sum+=g[x][j],x=f[x][j];

        if(f[x][0]==1&&sum+g[x][0]<=k){

            a[++cnta]=(nd){k-sum-g[x][0],x};

        }else vis[x]=true;

    }

 

    feng(1);//搜索已经被封的节点

    if(vis[1])

         return true;

    for(reg int i=head[1];i;i=e[i].nxt)

    if(!vis[e[i].to])b[++cntb]=(nd){e[i].dis,e[i].to};

    if(cnta<cntb)

         return false;

 

    reg int zz2=1;

    sort(a+1,a+cnta+1);

    sort(b+1,b+cntb+1);

    for(reg int i=1;i<=cnta&&zz2<=cntb;++i)

    {//判断答案

        if(!vis[a[i].d])

             vis[a[i].d]=true;

         else

         {

            while(vis[b[zz2].d]&&zz2<=cntb)

                  ++zz2;

            if(zz2>cntb)

                  return true;

            if(a[i].num>=b[zz2].num)

                  vis[b[zz2++].d]=true;

        }

 

        while(vis[b[zz2].d]&&zz2<=cntb)

             ++zz2;

    }

    return zz2>cntb;

}

 

int main()

{

    reg ll ans=-1,l=0,r=0;

    cnt=0;

    memset(head,0,sizeof head);

    memset(dep,0,sizeof dep);

    memset(f,0,sizeof f);

    memset(g,0,sizeof g);

    n=readint();

 

    for(reg int i=1;i<n;++i)

    {

        reg int u=readint(),v=readint(),t=readint();

        r+=t;

        e[++cnt]=(edge){v,t,head[u]};

        head[u]=cnt;

        e[++cnt]=(edge){u,t,head[v]};

        head[v]=cnt;

    }

 

    m=readint();

    for(reg int i=1;i<=m;++i)

         p[i]=readint();

 

    dep[1]=1;

    Dfs(1);

    for(reg int j=1;j<17;++j)//预处理++

    for(reg int i=1;i<=n;++i)

    {

        f[i][j]=f[f[i][j-1]][j-1];

        g[i][j]=g[f[i][j-1]][j-1]+g[i][j-1];

    }

 

    while(l<=r)

    {//二分

        reg ll mid=(l+r)>>1;

        if(ok(mid))r=(ans=mid)-1;else

        l=mid+1;

    }

 

    printf("%lld\n",ans);

 

    return 0;

}


IT航班提供:教辅资料、课程视频、课程书籍、竞赛辅导、少儿编程指导、课程采购、加盟、少儿编程资料、少儿编程课程、保送生、特长生、加分、中小学计算机教育、中小学信息学、竞赛、中小学信息学课程、人工智能、中小学编程加盟、少儿编程加盟、品牌加盟、技术加盟、技术指导、课程加盟、师资培训、中小学编程教辅资料、中小学编程教师培训、少儿编程教学书籍、少儿编程视频、教学书籍、教师培训、教学视频、CSP-J/S、中小学信息学课程服务、竞赛指导、课程提供、国内外计算机中小学计算机竞赛、信息学竞赛、信息学课程提供商、信息学奥林匹克。

 

 

IT航班支持----中小学编程比赛汇总:

 

第一部分:国内比赛(IT航班支持)   

1、软件能力认证(CSP-JS) 

2、全国青少年信息学奥林匹克联赛(NOIP)    

3、全国青少年信息学奥林匹克竞赛(NOI)

4、中国青少年………………………  

5、………………………创新挑战赛  

6、全国青少年………………………  

7、………………………

8、 恩欧希教育信息化发明创新奖  

9、世界机器人大赛(WRC) 

10、………………………大赛    

11、少………………………智能教育成果展示大赛 

12、“明天小小科学家”奖励活动

13、………………………    

14、………………………    

15、国际信息学……………………… 

16、………………………    

 

第二部分:国际比赛(IT航班支持)   

17、………………………    

18、国际………………………    

19、………………………

20、美国信息学……………………… 

21、加拿大……………………… 

22、官方邀请赛 (CCO)     

23、国际计算思维………………………    

24、美国计算机……………………… 

25、澳大利亚………………………    

 

第三部分:企业比赛(IT航班支持)   

26、微软MTA    

27、………………………挑战赛 

28、………………………科学奖 

29、………………………学奖    

30、………………………创新挑战赛 

31、………………………挑战赛 

32、………………………芯计算机表演赛 

33、………………………大赛    

 

第四部分:Scratch相关竞赛(IT航班支持)    

34、全国中小学生电脑制作大赛     

35、………………………    

36、………………………    

37、………………………    

 

第五部分:其它(IT航班支持)   

38、NOI夏令营  

39、NOI冬令营(NOIWC)  

40、全国青少年……………………… 

41、国际青少年………………………

 

联系方式:

A、官方网址:

http://www.itflight.net


B、微信公众号:

添加微信,获取资料。

image.png

 



关注公众号,获取动态。

image.png