群赛2总结(误)

来源:互联网 发布:如何修改游戏数据 编辑:程序博客网 时间:2024/05/16 16:16

  • T1
    • 题意
    • 题解
  • T2
    • 题意
    • 题解
  • T3
    • 题意
    • 题解
  • T4
    • 题意
    • 题解
  • T5
    • 题意
    • 题解
  • 总结

T1

题意

有一长度为n的数组,问是否能分为奇数段首尾均为奇数且长度为奇数的数组

题解

显然在n为偶数时无法分成奇数个奇数段,再判断最前与最后两个数就行。
因为可以 奇数+(n-2)个数+奇数

#include<bits/stdc++.h>using namespace std;int n,i,a[110],ji=0,k,ou=0,ans=1;int main(){    scanf("%d",&n);    for(i=1;i<=n;i++){scanf("%d",&a[i]);}    if(n%2==0)printf("No");    else    {    for(i=1;i<=n;i++)    {        if(i==1||i==n)        {            if(a[i]%2==0)            {                printf("No");                return 0;            }        }    }    printf("Yes");    }    return 0;}

T2

题意

已知一长度为n的数组作为n个点的纵坐标,其横坐标为1-n。问能否找到两条平行且不重叠的线段使所有点都在线段上。

题解

定义一个求斜率的函数,求出前三个点的相互的斜率找满足条件的,如有为是,没有为否。因为前三点不能在同一线上。
#include<bits/stdc++.h>using namespace std;int n,i,a[1010];bool xielv(double x)  {      int k=0;      for(i=2; i<=n; i++)      {          if(a[i]-a[1]==(i-1)*x)continue;          if(k==0)k=i;          else if(a[i]-a[k]!=(i-k)*x)return 0;      }      return k!=0;  }  int main(){    scanf("%d",&n);    for(i=1;i<=n;i++)scanf("%d",&a[i]);    if(xielv(a[2]-a[1])||xielv((a[3]-a[1])/2.0)||xielv(a[3]-a[2]))printf("Yes");      else printf("No");      return 0;}

T3

题意

给你一个数k,要求得到一个满足价值为k一种诡异操作的字符串

题解

发现每个数的价值最小为n*(n+1)/2,高斯求和(滑稽)此外k=0时只要输出a就行
#include<bits/stdc++.h>using namespace std;int k,i,cnt,ans,num,sum;int main(){    scanf("%d",&k);    if(k==0)    {        printf("a\n");        return 0;    }    while(k>0)    {        ans=num=sum=0;        while(k>=sum){ans=sum;num++;sum+=num;}        k-=ans;        for(i=1;i<=num;i++)printf("%c",'a'+cnt);        if(k<=0)break;        cnt++;    }    return 0;}

T4

题意

已知一个诡异的数k,你需要输出一个2^k^2的方阵,其中+表示1,*表示-1,时这若干对向量的积的和为0

题解

一道丧病的找规律,大概是:f[i][j]=f[i+n][j]=f[i][j+n]!=f[i+n][j+n]n是2的2-9次方先把所有的表打好就行
#include<bits/stdc++.h>#define q 1111using namespace std;int k,n,a[q][q],x,j,i,tmp;void xl(){    a[1][1]=1;    a[1][2]=1;    a[2][1]=1;    a[2][2]=0;    for(x=2;x<=9;x++)    {        n=1<<(x-1);        for(i=1;i<=n;i++)        {            for(j=1;j<=n;j++)            {                tmp=a[i][j];                a[i+n][j]=tmp;                a[i][j+n]=tmp;                a[i+n][j+n]=!tmp;            }        }    }}int main(){    xl();    scanf("%d",&k);    for(i=1;i<=1<<k;i++)    {        for(j=1;j<=1<<k;j++)        {            if(a[i][j]==1)printf("+");            else printf("*");        }        printf("\n");    }    return 0;}

T5

题意

给出一个长度为n的序列,然后有m次询问,每次询问给出a, b,然后计算[a,b]中所有素数的F(x)之和,F(x)为计算序列中有几个数为x的倍数。

题解

在暴力算法疯狂T+RE+WA后我换了种暴力法。。。输入这n个数的时候统计数出现多少次,然求每个素数被哪些数整除了的次数。然后输入l,r,就可以直接输出 dp[r]-dp[l-1],相减其实就是等于dp[l]到dp[r]之间的素数被整除的次数相加。
#include<bits/stdc++.h>using namespace std;int n,i,j,a,l,m,r,x[10000002],dp[10000002];  int main()  {      scanf("%d",&n);      for(i=0;i<n;i++) scanf("%d",&a),x[a]++;      for(i=2;i<10000002;i++)          if(dp[i]>=0)          {              dp[i]=x[i];              for(j=i*2;j<10000002;j+=i)                  dp[i]+=x[j],dp[j]=-1;          }      for(i=2;i<10000002;i++) dp[i]=(dp[i]<0?0:dp[i])+dp[i-1];      scanf("%d",&m);      for(i=0;i<m;i++)      {          scanf("%d %d",&l,&r);          if(r>=10000002) r=10000000;          l>r?printf("0\n"):printf("%d\n",dp[r]-dp[l-1]);      }      return 0;  }  

总结

这次比赛发挥有些水(西格玛公式读不懂233)导致T5光理解就用了好久,再加上纯暴力的时间内存弊端导致T4没时间做(然而你也看不懂T4)之后要加强英文理解能力与数学公式辨识能力。
原创粉丝点击