西北工业大学省赛选拔!!!

这次打的超级不好

1.直接上手E题结果那个输入的最后一个是5 1OOOOOOO/9999999 其中是O 而不是0

然后本来可以一血的,结果卡了好久也没过

2 ABC暴力题刚开始没认真读题然后就姿势不对,一直到自己明白题意才过

3 F题当时没几个人过感觉会很难,没做其实是签到题!!!

4 做题太慢导致D题没有好好思考,也就没好好做

A https://vjudge.net/problem/UVALive-7091

B https://vjudge.net/problem/UVALive-7092

C https://vjudge.net/problem/UVALive-7094

D https://vjudge.net/problem/UVALive-7095

E https://vjudge.net/problem/UVALive-7096

F https://vjudge.net/problem/UVALive-7097


A:

读入数据初始化vis数组,push优先队列(权值大的优先)

从大到小站队,用vis数组记录这个还在不在,然后top的下标的后面的人数加起来就是这个人站队需要的次数! 

最后 vis清零该节点 pop,输出ans就行了。

#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int num[25];
bool vis[25];
struct node
{
    int data;
    int ord;
    bool friend operator < (const struct node a,const struct node b)
    {
        return a.data<b.data;
    }
};
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
         priority_queue<node> que;
         int cnt;
         struct node u;
         scanf("%d",&cnt);
         for(int i=1;i<=20;i++)
         {
             scanf("%d",&u.data);
             u.ord=i;
             que.push(u);
             num[i]=i;
             vis[i]=1;
         }
         int ans=0;
         while(!que.empty())
         {
             u=que.top(); que.pop();
             for(int i=u.ord+1;i<=20;i++)
             {
                 ans+=vis[i];
             }
             vis[u.ord]=0;
         }
        printf("%d %d\n",cnt,ans);
    }
    return 0;
}

B:问有几个区间,其中包含的数都大于 左-1和右+1 的值

题意:

暴力枚举起点和终点,模拟即可

#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;

int  num[16];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int cnt;
        scanf("%d",&cnt);

        for(int i=1;i<=12;i++)
        {
            scanf("%d",&num[i]);
        }

        int ans=0;
        for(int i=2;i<=11;i++)
        {
            for(int j=i;j<=11;j++)
            {
                bool ssc=1;
                for(int k=i;k<=j;k++)
                {
                    if(num[k]<=num[i-1]||num[k]<=num[j+1]) { ssc=0; break;}
                }
                if(ssc) ans++;
            }
        }
        printf("%d %d\n",cnt,ans);
    }
    return 0;
}


C:题意判断是否是happ+质数(happy各个位的数值的平方之和 递归如果出现1 则 是happy num)

{

     1.素数用素数筛,微大于O(n)的复杂度  

     2.当时懒得想判断是否有循环,直接循环100次如果没有出现过happy就说明不是happy

}

#include <iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxn=1e5+100;
bool pim[maxn];

void get()
{
    memset(pim,1,sizeof(pim));
    pim[1]=0;
    for(int i=2;i<maxn;i++)
    {
        if(pim[i])
        {
            for(int j=2*i;j<maxn;j+=i)
            {
                pim[j]=0;
            }
        }
    }
}

int getnum(int num)
{
    int x=num;
    int ans=0;
    while(x)
    {
        int  flag=x%10;
        ans+=(flag*flag);
        x/=10;
    }
   return ans;
}

bool dfs(int pos,int step)
{
    if(step>=100) return 0;
    if(pos==1) return 1;
    return dfs(getnum(pos),step+1);
}


int main()
{
    int T;
    scanf("%d",&T);
    get();
    while(T--)
    {
        int cnt,num;
        scanf("%d %d",&cnt,&num);
        if(pim[num]&&dfs(num,0))
        {
            printf("%d %d YES\n",cnt,num);
        }
        else
        {
            printf("%d %d NO\n",cnt,num);
        }
    }
    return 0;
}

D

个人感觉D题是最难的一道题,当时没来得及做



插入当时侍聚聚手推过程。我也是赛后看他的代码才明白是什么规律。

预处理答案即可

{

      1.将i-1的长度和值全部都塞给i;

      2.扫一遍{

                         ->1. 如果是大于0的数 ,--即可

->2.如果第j个位置是0的话,改成j ,结束循环

     }

      3.如果每个数值都大于0,将len[i]++;然后 ans[k][len[i]]=len[i];

      4.输出每十个换一次行,为了这个pe了一发

}

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int ans[2010][85];
int len[2010];
int main ()
{
    memset(ans,0,sizeof(ans));
    memset(len,0,sizeof(len));
    len[0]=1;
    for(int i=1;i<=2000;i++)
    {
        len[i]=len[i-1];
        for(int j=1;j<=len[i];j++)
        {
            ans[i][j]=ans[i-1][j];
        }
        for(int j=1;j<=len[i];j++)
        {
            if(ans[i][j])
            {
                ans[i][j]--;
            }
            else
            {
                ans[i][j]=j;break;
            }
        }
        if(ans[i][len[i]]==len[i]-1) { len[i]++; ans[i][len[i]]=len[i] ;}
    }
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int cnt,k;
        scanf("%d%d",&cnt,&k);
        printf("%d %d\n",cnt,len[k]);
        int tt=0;
        for(int i=1;i<=len[k];i++)
        {
            ++tt;
            printf("%d",ans[k][i]);
            if(tt==10)
            {
                printf("\n");tt=0;
            }
            else if(i!=len[k]) printf(" ");
        }
        if(len[k]%10) printf("\n");
    }
    return 0;
}


E题真是血崩。

题意  父亲节点为p/q ,左儿子 p/(p+q) 右儿子 (p+q)/q; 给一点求它的下一个点

做法

{    

      讨论即可

     1.当 q==1 的时候 输出 1/p+1;

     2.当p<q 的时候  输出 q/q-p;

     3. 当p>q 递归向上until  p<q(同时记录递归了多少层)再求记录层数的左子树即可

}

#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
void work(int cnt,long long p,long long q)
{
     if(q==1)
     {
           printf("%d %lld/%lld\n",cnt,q,p+1);
           return;
     }
    else if(p<q)
    {
           printf("%d %lld/%lld\n",cnt,q,q-p);
           return;
    }
    else
    {
          long long pp=p,qq=q;
          long long step=0;
          while(1)
          {
              if(pp<qq) break;
              pp=pp-qq;
              step++;
          }
          long long x,y;
          x=pp; y=qq;
          pp=y;
          qq=y-x;
          while(1)
          {
              if(step==0) break;
              pp=pp;
              qq=pp+qq;
              step--;
          }
          printf("%d %lld/%lld\n",cnt,pp,qq);
    }
}


int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
       int cnt;
       long long p=0,q=0;
       scanf("%d %d/%d",&cnt,&p,&q);
       work(cnt,p,q);
    }
    return 0;
}

//5 1/1OOOOOOO

F  其实是个大水题。后悔啊。

 只有正号 讨论x,y的大小就可以了。

 x<y 2步 否则6步即可;

#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int ax[25];
int ay[25];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int tt,x,y;
        scanf("%d%d%d",&tt,&x,&y);
        if(x<y)
        {
            printf("%d %d %d %d\n",tt,2,x,y);
        }
        else
        {
            if(x+2<=x-y+5) printf("%d NO PATH\n",tt);
            else printf("%d %d %d %d %d %d %d %d\n",tt,6,1,2,3,x-y+5,x+2,x+3);
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值