第三次校内排位赛暨上大校赛题解+反思+总结

第三次校内排位赛暨上大校赛题解+反思+总结

total:15 ac:6 rank:96

部分题解

B 神无月排位赛

直接模拟即可。注意分数在[0,100],等级只有D,C,B,A,S

D 添加好友

\(\sum_{i=1}^{n}C_n^i=2^n-1\)

E 字符串进制转换

直接模拟即可,注意爆int与a,aa,aaa这类数据

F A序列

正向反向求一遍最长递增子序列,再遍历一遍,找到正反向长度相同时的最大长度ans,输出ans*2-1即可

G 战斗

暴力枚举全排列,再计算即可。计算时发现怪兽-怪兽和按秒计算都有过,可能是1.数据弱 2.除法比减法慢,附上两份代码

//怪兽-怪兽
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
using namespace std;
int _,n;
bool can;
struct ss
{
    int v,a;
};
ss a[11],b[11],c[11],d[11];
bool vis[11];
int x[11];
void dfs(int t)
{
    if (can) return;
    if (t>n)
    {
        int i=1,j=1;
        for (i=1;i<=n;i++)
        {
            c[i]=a[i];
            d[i]=b[i];
        }
        i=1;
        //cout<<x[1]<<" "<<x[2]<<endl;
        //cout<<"hhhhhhhhh"<<endl;
        while (i<=n&&j<=n)
        {
            while (c[i].v>0&&d[x[j]].v>0)
            {
                int t=c[i].v/d[x[j]].a;
                if (c[i].v%d[x[j]].a) t++;
                int u=d[x[j]].v/c[i].a;
                if (d[x[j]].v%c[i].a) u++;
                if (t<u)
                {
                    c[i].v=0;
                    d[x[j]].v-=c[i].a*t;
                    //i++;
                }
                else if (t>u)
                {
                    d[x[j]].v=0;
                    c[i].v-=d[x[j]].a*u;
                    //j++;
                }
                else
                {
                    c[i].v=0;
                    d[x[j]].v=0;
                    //i++;
                    //j++;
                }
                //cout<<i<<" "<<x[j]<<" "<<c[i].v<<" "<<d[x[j]].v<<endl;
            }
        //  cout<<i<<" "<<x[j]<<" "<<c[i].v<<" "<<d[x[j]].v<<endl;
            if (c[i].v<=0) i++;
            if (d[x[j]].v<=0) j++;
        }
        if (i>n&&j<=n) can=true;
    }
    else
    {
        int i;
        for (i=1;i<=n;i++)
        if (!vis[i])
        {
            vis[i]=true;
            x[t]=i;
            if (can) return;
            dfs(t+1);
            if (can) return;
            vis[i]=false;
        }
    }
}
int main()
{
    scanf("%d",&_);
    while (_--)
    {
        scanf("%d",&n);
        int i;
        for (i=1;i<=n;i++)
            scanf("%d%d",&a[i].v,&a[i].a);
        for (i=1;i<=n;i++)
            scanf("%d%d",&b[i].v,&b[i].a);
        can=false;
        memset(vis,false,sizeof(vis));
        dfs(1);
        if (can) puts("YES"); else puts("NO");
    }
    return 0;
}
//按秒计算
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
//#pragma comment(linker, "/STACK:102400000,102400000")
//inline void read(int &x){x=0; char ch=getchar();while(ch<'0') ch=getchar();while(ch>='0'){x=x*10+ch-48; ch=getchar();}}

int t,n;
struct node
{
    int live,attack;
}a[12],b[12],aa[12],bb[12];
int num[12],cou;

int main()
{
    for(scanf("%d",&t);t--;)
    {
        scanf("%d",&n);
        F(i,1,n) scanf("%d %d",&a[i].live,&a[i].attack);
        F(i,1,n) scanf("%d %d",&b[i].live,&b[i].attack);
        cou=1;
        F(i,1,n) { num[i]=i;cou*=i; }
        F(k,1,cou)
        {
            next_permutation(num+1,num+1+n);
            //F(i,1,n) printf("%d%c",num[i],i==n?'\n':' ' );
            F(i,1,n) aa[i].live=a[i].live,aa[i].attack=a[i].attack,bb[num[i]].attack=b[i].attack,bb[num[i]].live=b[i].live;//a--cpu,b---ren
            int loc1=1,loc2=1;
            while(loc1<=n&&loc2<=n)
            {
                //int live1=aa[loc1].live,attack1=aa[loc1].attack,live2=bb[loc2].live,attack2=bb[loc2].attack;
                //int c=min(live1/attack2,live2/attack1);
                //aa[loc1].live-=c*attack2,bb[loc2].live-=c*attack1;
                while(aa[loc1].live>0&&bb[loc2].live>0) aa[loc1].live-=bb[loc2].attack,bb[loc2].live-=aa[loc1].attack;
                if(aa[loc1].live<=0) loc1++;
                if(bb[loc2].live<=0) loc2++;
            }
            if(loc1>n&&loc2<=n) { puts("YES");goto loop; }
            //F(i,1,n) printf("%d %d\n",aa[i].live,aa[i].attack);puts("");
        }
        puts("NO");
        loop:;
    }
    return 0;
}

H 调和序列

将所有的询问保存下来,按k排序,每次如果k不变直接输出,k变化重新生成序列,再输出(一次性输出答案),附上代码

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
//#pragma comment(linker, "/STACK:102400000,102400000")
//inline void read(int &x){x=0; char ch=getchar();while(ch<'0') ch=getchar();while(ch>='0'){x=x*10+ch-48; ch=getchar();}}

int t;
int n,m;
int a[20020],b[20020],d[100100];
int k,big,len=0;
struct node
{
    int k,big,id;
    bool operator<(const node &p)const
    {
        return k<p.k;
    }
}c[100100];
int main()
{
    for(scanf("%d",&t);t--;)
    {
        scanf("%d %d",&n,&m);
        F(i,1,n) scanf("%d",a+i);
        F(i,1,m)
        {
            scanf("%d %d",&c[i].k,&c[i].big);
            c[i].id=i;
        }
        sort(c+1,c+1+m);
        F(i,1,m)
        {
            if(c[i].k==c[i-1].k) d[c[i].id]=c[i].big>len?-1:b[len-c[i].big+1];
            else
            {
                len=(n-1)/c[i].k+1;
                for(int j=0;j<len;++j) b[j+1]=a[j*c[i].k+1];
                sort(b+1,b+1+len);
                //F(j,1,n) printf("%d%c",b[j],j==n?'\n':' ' );
                d[c[i].id]=c[i].big>len?-1:b[len-c[i].big+1];
            }
        }
        F(i,1,m) printf("%d\n", d[i]);
    }
    return 0;
}

I 丢史蒂芬妮

直接暴力枚举素数,如果dp[i-k][j],dp[i][j-k],dp[i-k][j-k]有一个是必败点,那么该点为必胜点,否则为必败点

J 膜一下将带给你好运

原式=\((n+1)*n/2-\sum_1^{232}phi(i)(\frac ni)-\sum_{n-232}^{n}phi(i)\frac in\)

证明:就是n/i其实就是i在n以内的倍数个数
交换内外层就是枚举i,再枚举i的约数d,求phi(d)的和
然后i的约数的phi的和是i

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
//#pr0agma comment(linker, "/STACK:102400000,102400000")
//inline void read(int &x){x=0; char ch=getchar();while(ch<'0') ch=getchar();while(ch>='0'){x=x*10+ch-48; ch=getchar();}}

int t;
int n,m;
int dp[555][555];
const int maxn=500;
int prime[maxn+10];
bool p[maxn+10];

void get_prime()
{
   F(i,2,maxn)
   {
      if(!p[i]) prime[++prime[0]]=i;
      for(int j=1;j<=prime[0]&&i*prime[j]<=maxn;++j)
      {
         p[i*prime[j]]=1;
         if(i%prime[j]==0) break;
      }
   }
   //F(i,1,prime[0]) printf("%d\n",prime[i]);
}
int main()
{
        get_prime();
        //mem(dp,0);
        //dp[0][0]=dp[1][0]=dp[0][1]=dp[1][1]=0;
        for(int i=1;i<=500;++i)for(int j=1;j<=500;++j)
        {
            for(int k=1;k<=prime[0]&&prime[k]<j;k++) if(!dp[i][j-prime[k]]) {dp[i][j]=1;goto loop;}
            for(int k=1;k<=prime[0]&&prime[k]<i;k++) if(!dp[i-prime[k]][j]) {dp[i][j]=1;goto loop;}
            for(int k=1;k<=prime[0]&&prime[k]<j&&prime[k]<i;k++) if(!dp[i-prime[k]][j-prime[k]]) {dp[i][j]=1;goto loop;}
                loop:;
        }
        //R(i,0,10)R(j,0,10) printf("%d%c",dp[i][j],j==9?'\n':' ' );
        //F(i,1,10)F(j,1,10) printf("%d%c",dp[i][j],j==10?'\n':' ' );
        
    for(scanf("%d",&t);t--;)
    {
        scanf("%d %d",&n,&m);//n--,m--;
        //F(i,1,10)F(j,1,10) printf("%d%c", dp[i][j],j==10?'\n':' ');
        if(!dp[n][m]) puts("Shiro");else puts("Sora");
    }
    
    return 0;
}

K 购买装备

首先求出购买装备的最大数量,再根据价值排序,二分位置pos,并对[pos,n]按花费排序,满足\(\sum_{pos}^{pos+maxnum-1}cost_i \le m\)的条件下使得pos最大,附上代码参考

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
//#pragma comment(linker, "/STACK:102400000,102400000")
//inline void read(int &x){x=0; char ch=getchar();while(ch<'0') ch=getchar();while(ch>='0'){x=x*10+ch-48; ch=getchar();}}

int t;
int n,money;
int bignum,maxval;
struct node
{
    int val,cost;
}c[100100],d[100100];
bool cmp1(node x,node y)
{
    return x.val<y.val;
}
bool cmp2(node x,node y)
{
    return x.cost<y.cost;
}
bool judge(int mid)
{
    int ret=0;
    memcpy(d,c,sizeof(c));
    if(n-mid+1<bignum) return 0;
    sort(d+mid,d+1+n,cmp2);
    F(i,mid,mid+bignum-1) ret+=d[i].cost;
    //sort(c+mid,c+1+n,cmp1);
    return ret<=money;
}
int main()
{
    for(scanf("%d",&t);t--;)
    {
        scanf("%d%d",&n,&money);
        F(i,1,n) scanf("%d %d",&c[i].val,&c[i].cost);
        sort(c+1,c+1+n,cmp2);
        int ret=0;maxval=2e9;bignum=0;
        F(i,1,n)
        {
            ret+=c[i].cost;
            if(ret>money) break;
            bignum++;maxval=min(maxval,c[i].val);
        }
        sort(c+1,c+1+n,cmp1);
        int left=1,right=n,mid;
        while(left<right)
        {
            mid=(left+right+1)/2;
            if(judge(mid)) left=mid;else right=mid-1;
        }
        mid=(left+right)/2;
        printf("%d %d\n", bignum,c[mid].val);
    }
    return 0;
}

反思

这场比赛由于自身实力和一些不可控因素,战绩惨淡。开场网络巨大延迟,看不了题,心态逐渐变差。到后来拿到了pdf,心里已经很放弃,带着很随意地心态去写题,碰到模拟不想写,碰到稍难题不想思考,比赛时带着一种放弃的心
态。反映出我在巨大压力下(不能判断自己代码正确与否,不能更榜)下的几个弱点:
1.代码能力弱,会有很多变量名/数组未清空等bug
2.读代码能力弱,因为习惯于手打输出,需要脑中运行代码,但速度慢
3.临场心态稳定性太差,如上描述

总结

A序列想了好久,
战斗代码写了好久还wa了,没时间去重写了
调和序列想成分块,一开始就放弃了
丢史蒂芬妮发现最后输出变成了'Sore',
膜一下没有减去1~232和n-232~n两块
购买装备没想清楚,QAQ
实力和心态都不好,导致了该场的惨败,下一阶段目标
1.看挑战指南数据结构及数论一块
2.每天一场cf
3.下次比赛正常发挥 18-/36
加油吧,骚年

转载于:https://www.cnblogs.com/chendl111/p/7145168.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值