牛客小白月赛18-记录

正题

比赛链接:https://ac.nowcoder.com/acm/contest/1221


成绩

在这里插入图片描述
在这里插入图片描述


总结

好难,就拿了一些水题分


T1:Forsaken喜欢数论 \texttt{T1:Forsaken喜欢数论} T1:Forsaken喜欢数论

题目大意

f ( i ) f(i) f(i)表示 i i i的最小质因子,求 ∑ i = 2 n f ( i ) \sum_{i=2}^nf(i) i=2nf(i)

解题思路

线性筛就是用每个数的最小质因子把这些数筛掉,所以筛的时候统计就好了

c o d e code code

#include
#include
#include
#define ll long long
using namespace std;
ll n,cnt,prime[6893911*3],ans;
bool v[10000001*3];
int main()
{
    scanf("%lld",&n);
    v[1]=1;
    for(ll i=2;i<=n;i++){
        if(!v[i]) prime[++cnt]=i,ans+=i;
        for(ll j=1;j<=cnt&&i*prime[j]<=n;j++)
        {
            v[prime[j]*i]=1;
            ans+=prime[j];
            if(!(i%prime[j])) break;
        }
    }
    printf("%lld",ans);
}

T2:Forsaken喜欢字符串 \texttt{T2:Forsaken喜欢字符串} T2:Forsaken喜欢字符串

题目大意

对于一个字符串的子串的价值是在其他字符串里有多少个和它相同的子串。

n n n个字符串,每次询问第 x x x个字符串长度为 l e n len len的子串的价值之和是多少

解题思路

我们发现每个字符串的长度都很小,所以我们可以暴力字符串 h a s h + m a p hash+map hash+map库来统计

要注意的是不能算上自己这个字符串,所以每次询问时在开一个 m a p map map,再用两个相减

c o d e code code

#include
#include
#include
#include
using namespace std;
const int N=5e4+10;
int n,k,m;
map<int,int> v,now;
char s[N][6];
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%s",s[i]);
        for(int l=0;l<k;l++){
            int z=0;
            for(int r=l;r<k;r++){
                z+=s[i][r]-'a'+1;z*=27;
                v[z]+=r-l+1;
            }
        }
    }
    scanf("%d",&m);
    while(m--){
        int x,len;
        scanf("%d%d",&x,&len);
        now.clear();int ans=0;
        for(int l=0;l<k;l++){
            int z=0;
            for(int r=l;r<k;r++){
                z+=s[x][r]-'a'+1;z*=27;
                now[z]+=r-l+1;
            }
        }
        for(int l=0;l<k;l++){
            int z=0;
            if(l+len>k) continue;
            for(int r=l;r<min(l+len,k);r++)
                z+=s[x][r]-'a'+1,z*=27;
            ans+=v[z]-now[z];
        }
        printf("%d\n",ans);
    }
}

T3:Forsaken给学生分组 \texttt{T3:Forsaken给学生分组} T3:Forsaken给学生分组

题目大意

n n n个数分为 k k k组,每组的价值是最大的数减去最小的数。求最大价值和

解题思路

显然我们可以贪心选取,需要注意的是若 k > n 2 k>\frac{n}{2} k>2n,那么有些就得单独一组

c o d e code code

#include
#include
#include
#define ll long long
using namespace std;
const ll N=1e5+10;
ll n,k,a[N],ans;
int main()
{
    scanf("%lld%lld",&n,&k);
    for(ll i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    sort(a+1,a+1+n);
    if(k>n/2) k=n-k;
    for(ll i=1;i<=k;i++)
        ans+=a[n-i+1]-a[i];
    printf("%lld",ans);
}

T4:Forsaken喜欢正方形 \texttt{T4:Forsaken喜欢正方形} T4:Forsaken喜欢正方形

题目大意

求四个点能不能组成正方形,或者微调之后能不能组成正方形。

解题思路

考试的时候直接匹配了 4 4 4条边相等(没有判断菱形)就过了,如果要判断菱形就加一个判断对角线是不是边长的 2 \sqrt2 2 倍就好了,这里就不加先了

c o d e code code

#include
#include
#include
using namespace std;
int x[5],y[5];
const int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int get_dis(int a,int b)
{return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);}
bool check()
{
    int l1=get_dis(1,2),l2=get_dis(2,3),l3=get_dis(3,4),l4=get_dis(4,1);
    if(l1==l2&&l2==l3&&l3==l4) return 1;
     
    l1=get_dis(1,2),l2=get_dis(2,4),l3=get_dis(4,3),l4=get_dis(3,1);
    if(l1==l2&&l2==l3&&l3==l4) return 1;
     
    l1=get_dis(1,3),l2=get_dis(3,2),l3=get_dis(2,4),l4=get_dis(4,1);
    if(l1==l2&&l2==l3&&l3==l4) return 1;
     
    l1=get_dis(1,3),l2=get_dis(3,4),l3=get_dis(4,2),l4=get_dis(2,1);
    if(l1==l2&&l2==l3&&l3==l4) return 1;
     
    l1=get_dis(1,4),l2=get_dis(4,2),l3=get_dis(2,3),l4=get_dis(3,1);
    if(l1==l2&&l2==l3&&l3==l4) return 1;
     
    l1=get_dis(1,4),l2=get_dis(4,3),l3=get_dis(3,2),l4=get_dis(2,1);
    if(l1==l2&&l2==l3&&l3==l4) return 1;
     
    return 0;
}
int main()
{
    for(int i=1;i<=4;i++)
        scanf("%d%d",&x[i],&y[i]);
    if(check()){printf("wen");return 0;}
    for(int i=1;i<=4;i++){
        for(int k=0;k<4;k++){
            x[i]+=dx[k];y[i]+=dy[k];
            if(check()){printf("hai xing");return 0;}
            x[i]-=dx[k];y[i]-=dy[k];
        }
    }
    printf("wo jue de bu xing");
}


T7:Forsaken的三维数点 \texttt{T7:Forsaken的三维数点} T7:Forsaken的三维数点

题目大意

一个三维空间以 ( 0 , 0 , 0 ) (0,0,0) (0,0,0)为中心,每次两个操作

  1. 加入一个能量球在 ( x , y , z ) (x,y,z) (x,y,z)
  2. 以中心半径为 k k k的球能够包括 x x x个能量球,求 k k k的最小整数值

解题思路

因为是 k k k的最小整数值,所以我们直接对于小数向上取整,然后二分+树状数组即可

c o d e code code

#include
#include
#include
#include
#define lowbit(x) x&-x
using namespace std;
const int N=2e5+10;
int n,t[N+10],l,r;
void change(int x,int z)
{
    while(x<=N){
        t[x]+=z;
        x+=lowbit(x);
    }
}
int ask(int x)
{
    int ans=0;
    while(x){
        ans+=t[x];
        x-=lowbit(x);
    }
    return ans;
}
double get_dis(double x,double y,double z)
{return sqrt(x*x+y*y+z*z);}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int op;double x,y,z;
        scanf("%d%lf",&op,&x);
        if(op==1){
            scanf("%lf%lf",&y,&z);
            double dis=get_dis(x,y,z);
            dis+=(((int)dis)!=dis);
            change((int)dis,1);
        }
        else{
            l=0;r=N;
            while(l<=r){
                int mid=(l+r)/2;
                if(ask(mid)<(int)x) l=mid+1;
                else r=mid-1;
            }
            if(ask(l)<(int)x) printf("-1\n");
            else printf("%d\n",l);
        }
    }
}

你可能感兴趣的:(模拟赛)