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


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

    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?'
    ':' ' );
        		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
    ",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?'
    ':' ' );
        			d[c[i].id]=c[i].big>len?-1:b[len-c[i].big+1];
        		}
        	}
        	F(i,1,m) printf("%d
    ", 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
    ",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?'
    ':' ' );
            //F(i,1,10)F(j,1,10) printf("%d%c",dp[i][j],j==10?'
    ':' ' );
            
        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?'
    ':' ');
            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
    ", 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
    加油吧,骚年

  • 相关阅读:
    数据结构做题一些总结
    ExecuteNoQuery执行, 报错“go”附近有语法错误。
    EF总结
    哨兵模式
    Redis 发布订阅
    Redis 持久化
    Redis 事务 和乐观锁
    缓存穿透和雪崩
    Redis 基础知识
    Redis 三种特殊的数据类型
  • 原文地址:https://www.cnblogs.com/chendl111/p/7145168.html
Copyright © 2020-2023  润新知