第六届山东省省赛题解

A - Nias and Tug-of-War

题意:

给出n个人的身高和体重

要求按身高排序后

奇数序号的人一队,偶数序号的人一队

体重大的一队获胜

题解:

水题,考察点是结构体的排序

要注意的是变量的初始化以及数据类型的精度和输入

代码:

struct Node {
    double w, h;
} a[110];

bool cmp (Node a, Node b) {
    return a.h < b.h;
}

int main()
{
    int t, n;
    scanf("%d", &t);
    while (t--) {
        scanf("%d", &n);
        for (int i = 0; i < n; i++) {
            scanf("%lf %lf", &a[i].h, &a[i].w);
        }
        
        sort(a, a+n, cmp);
        double s1, s2;
        s1 = s2 = 0;
        for (int i = 0; i < n; i++) {
            if (i % 2) {
                s1 += a[i].w;
            } else {
                s2 += a[i].w;
            }
        }

        if (s1 > s2) {
            printf("blue\n");
        } else if (s1 < s2) {
            printf("red\n");
        } else {
            printf("fair\n");
        }
    }
    return 0;
}

B - Lowest Unique Price

题意:

给出N种操作,每种操作都由字母表示,当输入为b时,输入一个整数x,代表顾客对产品的出价,当输入为c是,输入一个整数x,代表取消之前价格为x的出价,当输入为q是,询问当前对产品的出价中只出现过一次的最小的价格,如果存在,输出该最小值,如果不存在,输出none。

题解:

开辟一个数组,用下标表示价格,该下标下元素的值代表该价格的出价次数,每当顾客出价时,将元素加一,并记录下当前出价的最大值max,若操作为取消之前的价格,就将数组减一即可;最后询问最小值的之后只要从一开始遍历到出价的最大值,找到第一个值为一的元素即可;

#include
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,a[200005]={0},max=0,x;
        char c;
        scanf("%d",&n);
        getchar();
        for(int i=0;i)
        {
            c=getchar();
            if(c=='b')
            {
                scanf("%d",&x);
                a[x]++;
                if(x>=max)
                    max=x;
            }
            if(c=='c')
            {
                scanf("%d",&x);
                a[x]--;
            }
            if(c=='q')
            {
                int flag=0,t;
                for(int j=1;j<=max;j++)
                    if(a[j]==1)
                    {
                        flag=1;
                        t=j;
                        break;
                    }
                if(flag==1)
                    printf("%d\n",t);
                else
                    printf("none\n");
            }
            getchar();
        }
    }
    return 0;
}

C - Game!

题型:

博弈

题意:

现有n个石头围成一圈

两个人轮流拿石头,可以拿一个或连续的两个

拿走最后石头的获胜

题解:

环形博弈

对于先手只可能在他能拿石子个数的范围内取胜,否则后手赢。

当石子个数多于两个的时候

对手只需要拿走先手所选择石子对面的石子就一定可以获胜

int main()
{
    int t;
    LL n;
    scanf("%d", &t);
    while (t--) {
        scanf("%lld", &n);
        if (n <= 2) {
            printf("zbybr\n");
        } else {
            printf("blankcqk\n");
        }
    }
    return 0;
}

F - BIGZHUGOD and His Friends II

题意:

三个人(三个人分别为1,2,3)站在三角形的三个顶点(1站在A上,2站在B上,3站在C上)上,另有一个人站在三角形内部(可以站在内部的任意位置),之后站在顶点上的三个人按照顶点顺序开始向相邻顶点跑动(1->B,2->C,3->A),当三个人中的任意一个人跑到另一个顶点的时候,游戏结束。给定三个人跑向相邻顶点所需要的时间,问站在三角形内部的那个人能否找到一个时刻,可以挡住视线(1->C,2->A,3->B),如果有,那就输出YES和这个时刻,输出到小数点后四位。如果没有,输出NO。

题解:

塞瓦定理:塞瓦定理是指在△ABC内任取一点O,延长AO、BO、CO分别交对边于D、E、F,则 (BD/DC)×(CE/EA)×(AF/FB)=1

 第六届山东省省赛题解_第1张图片

 

通过塞瓦定理,用二分求解方程即可。如果判断循环条件为low<=high时,会超时,题意要求精确到小数点后四位,所以判断条件可以改成fabs(n)>1e-5(n为方程的结果)。

#include
#include
#include<string.h>
#include
#include
#include
#define N 1000+10
#define inf 0x3f3f3f3f
#define LL long long
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int t1,t2,t3,flag=0;
        double low=0,high,mid,n;
        scanf("%d%d%d",&t1,&t2,&t3);
        high=min(t1,min(t2,t3));
        do
        {
            mid=(low+high)*0.5;
            n=(t1-mid)*(t2-mid)*(t3-mid)-mid*mid*mid//方程;
            if(n>0)
                low=mid;
            if(n<0)
                high=mid;
            if(n==0)
            {
                printf(".20lf\n",n);
                break;
            }
        }while(fabs(n)>1e-5);
        if((int)n==0)
            printf("YES %.4lf\n",mid);
        else
            printf("NO\n");
    }
    return 0;
}

 

 H - Square Number

题解:

平方数:某个整数的平方;

给定一串整数(a1,a2........an),求有多少对整数的乘积(ai*aj),使得这个乘积为平方数。

题解:

任何的平方数都可以分解成若干素数的偶次幂,先打表将所有素数的平方全部打出来,之后可以将每一个数先分解成若干素数的平方次幂,将分解后剩余的部分存入数组中,最后只需要找剩余部分相同的数两两匹配即可。

代码:

#include
#include
#include
#include<string.h>
#include
#include
#define N 10000000+10
#define LL long long
using namespace std;
int a[N],b[N],flag[N];
int main()
{
    int t,num=0;
    scanf("%d",&t);
    int m=sqrt(N)+1;
    for(int i=2;i<=m;i++)
    {
        if(b[i]==0)
        {
            a[num++]=i*i;
            for(int j=i+i;j<=m;j+=i)
                b[j]=1;
        }
    }
    while(t--)
    {
        int n,x;
        memset(flag,0,sizeof(flag));
        scanf("%d",&n);
        for(int i=0;i)
        {
            scanf("%d",&x);
            for(int j=0;a[j]<=x&&j<=num-1;j++)
                while(x%a[j]==0)
                {
                    x/=a[j];
                }
            flag[x]++;
        }
        LL ans=0;
        for(int i=1;i)
            ans+=flag[i]*(flag[i]-1)/2;
        printf("%lld\n",ans);
    }
    return 0;
}

 

J - Single Round Math

题意

给两个数n,m(0<=n,m<=10^1000),代表n个男人和m个 女人,问能否将其分成11组,使得每组男的数量等于女的数量。

题解

因为给的数太大,所以采用字符串处理。

同余定理

(a+b)%c=(a%c+b%c)%c;

(a*b)%c=(a%c*b%c)%c;

比如:

846%c=((8*10+4)*10+6)%c=(((8%c*10*c)%c+4%c)%c*10%c)%c+6%c)%c;

所以通过将字符串的每个字符转换成数字取余最后判断即可;

代码:

#include
#include
#include<string.h>
#include
#define N 10000000
using namespace std;
char n[N],m[N];
int main()
{
    int t;
    scanf("%d",&t);
    getchar();
    while(t--)
    {
        int a;
        scanf("%s%s",n,m);
        getchar();
        if(strcmp(n,m)==0)
        {
            a=n[0]-48;
            for(int i=1;i)
            {
                a=((a%11*10%11)%11+(n[i]-48)%11)%11;
            }
            if(a==0)
                printf("YES\n");
            else
                printf("NO\n");
        }
        else
            printf("NO\n");
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/aiguona/p/9211768.html

你可能感兴趣的:(第六届山东省省赛题解)