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

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

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
加油吧,骚年

原文地址:https://www.cnblogs.com/chendl111/p/7145168.html