比赛链接
http://www.bnuoj.com/v3/contest_show.php?cid=7468
总结:
本次比赛一共8题,其中AB为签到题,CD为简单题,EF为中档题,G题为防AK题(但是由于spj的问题放了一份错误代码通过),H题为构造题(但是出题人的最初想法有误,并且由于只需输出解的存在性,出现了读错题却AC的情况),各题通过人数与难度大致符合,梯度尚可。
A. BQG's Programming Contest
直接输出min(60000,max(1000,5*max(t1,t2)))即可。
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",min(60000,max(1000,5*max(a,b))));
}
return 0;
}
B. BQG's Messy Code
抄一遍代码可以发现这个程序会输出相反数,或者直接根据样例猜也可以。
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int x;
scanf("%d",&x);
printf("%d\n",-x);
}
return 0;
}
C. BQG's Approaching Deadline
先做晚布置的作业不会使答案更优,因此将所有作业按照布置时间从小到大排序之后扫一遍即可,复杂度O(nlogn),但是允许O(n^2)的排序通过。
#include
#include
#include
#include
#include
#include
using namespace std;
const int MAXN=1005;
struct hw
{
int a,b;
bool operator < (const hw &t)const
{
return a
D. BQG's Random String
直接模拟,复杂度O(n)。
#include
#include
#include
#include
#include
#include
using namespace std;
const char t[4]="QAQ";
char s[100005];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
int n=strlen(s),res=0;
for(int i=0;i+2
E. BQG's Complexity Analysis
在大O意义下比较两个时间复杂度的大小是认为n->+inf的,因此优先比较n的幂次,n的幂次相同时再比较log的幂次,那么只需要先把特殊情况特判掉,再从字符串中将对应幂次提取出来即可。
#include
#include
#include
#include
#include
#include
using namespace std;
char s[55];
pairc[5];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
for(int i=0;i<2;i++)
{
scanf("%s",s);
int loc=0;
if(s[2]=='1')
{
c[i]=make_pair(0,0);
continue;
}
else if(s[2]=='n')
{
loc=3;
if(s[3]=='^')
{
int pp=0;
loc++;
while(s[loc]>='0' && s[loc]<='9')
pp=pp*10+s[loc++]-'0';
c[i].first=pp;
}
else c[i].first=1;
}
else c[i].first=0;
if(s[loc]==')')c[i].second=0;
else
{
int pp=0,len=strlen(s);
while(loc'9'))loc++;
while(loc='0' && s[loc]<='9')
pp=pp*10+s[loc++]-'0';
if(pp==0)c[i].second=1;
else c[i].second=pp;
}
}
if(c[0]c[1])printf("Second\n");
else printf("Both\n");
}
return 0;
}
F. BQG's Confusing Sequence
需要分有0和没有0两种情况讨论,但是无论何种情形,混乱数都可以对应到二进制数,找到对应关系之后直接求出每一位的数字之后再取模即可,数位dp也是可以的,复杂度O(logn)。
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll Mod=1000000007LL;
int ty[55];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int a,b,n;
scanf("%d%d%d",&a,&b,&n);
if(a>b)swap(a,b);
if(a)n++;
int loc=0;
while(n)
{
ty[loc++]=n&1;
n>>=1;
}
ll res=0LL;
for(int i=loc-1-(a>0);i>=0;i--)
res=(res*10+(ty[i] ? b : a))%Mod;
printf("%lld\n",res);
}
return 0;
}
G. BQG's Square Glasses
由于折线上的点纵坐标>=1,因此除了最后一次切下来的正方形,其余正方形边长一定>=1,因此只会切出O(r)个正方形,直接按照题意模拟切正方形即可,那么问题在于每次如何找出最大的正方形,假设现在x<=p的玻璃都已经被舍去。
一个做法是,二分正方形的边长x(p+x<=r),检查折线在[p,p+x]这一段的y坐标的最小值是否>=x,由于折线的性质,y坐标的最小值一定在边界或者拐点处,只需对拐点的y坐标预处理区间最小值,边界处的y坐标直接计算即可,需要二分快速定位边界所在线段并计算y坐标,这样的复杂度是O(nlogn+rlogrlogn)的。
另一个做法是,过点(p,0)引一条斜率为1的直线,设直线与折线的交点横坐标为q(如果有多个交点取横坐标最小的,如果没有交点取q=r),那么最大正方形的边长即为折线在[p,q]这一段的y坐标的最小值,容易知道p,q都是单调递增的,可以维护两个单调往右走的指针来记录折线上横坐标分别为p,q的点所在的线段,维护一个单调队列来记录区间[p,q]中折线拐点的y坐标的最小值,这样的复杂度是O(n+r)的。
下面给出第一种做法的代码。
#include
#include
#include
#include
#include
#include
using namespace std;
typedef double db;
const int MAXN=100005;
const db INF=1e100;
const db eps=1e-12;
int sgn(db x)
{
if(x>eps)return 1;
if(x<-eps)return -1;
return 0;
}
db x[MAXN],y[MAXN];
db dp[MAXN][20];
int mm[MAXN];
void initRMQ(int n,db b[])
{
mm[0]=-1;
for(int i=0;imin(min(yl,yr),rmq(kl+1,kr)))tr=tm;
else tl=tm;
}
tl=(tl+tr)/2.0;
res+=(tl-l)*(tl-l);
l=tl;
}
printf("%.20f\n",res+(r-l)*(r-l));
}
return 0;
}
H. BQG's Quadrilateral Bricks
原题中“自相交四边形”这一情形已经被删去,现在题面已经修改,数据已经重做。
如上图,实际构造其实很简单,先将整个四边形关于某条边中点对称过去,得到一个中心对称图形,拉成一个无限长的条形之后可以发现两侧边界是相同的,利用这个长条就可以密铺整个平面,因此直接输出"BQG is happy!"即可。
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
for(int i=0;i<8;i++)scanf("%*d");
printf("BQG is happy!\n");
}
return 0;
}