第三次校内排位赛暨上大校赛题解+反思+总结
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
加油吧,骚年