SRM 473

昨天写了SRM474的部分题解,打算把这个坚持写下去,主要还是前两题,hhanger大牛说了,狂刷500的题就能红,狂刷1000就能Target,红不敢奢望,把去年这个时候的设想实现了,能黄就行。。。

 

 

 

DIV2

 

250P OnTheFarmDivTwo

 

两种动物,一种是鸡,一种是牛,有3个头,8条腿,这样就是有2只鸡,1头牛。给出头数和腿数,问分别有多少只鸡,多少头牛。

小学数学题,x, y代表鸡和牛数,联立方程组,消去x,得到y的表达式,注意要整除和不能为负。

 

 

500P SequenceOfCommands

 

你在二维平面上,起点在原点,初始面对方向为北方。现在要按照一串字符串指令行动,指令中包含3种字符,'S','R','L',S表示向前走一步,R表示右转90度,L表示左转90度。问,无限次执行这段指令后,你的行动轨迹是否可以用一个固定半径的圆包含进来。即,你的行动轨迹是否不是发散的。(发散指的是行动起点轨迹不断偏离起点)

 

分两种情况,一是执行完一次指令串以后回到起点,这样就是永远在一个固定范围内行动;二是执行完一次指令以后,在没有回到起点的情况下,指令完成时面向的方向不是北方(起点的方向),如果这样的话也是一直在绕圈圈,这样的轨迹当然也是永远在一个固定范围内了。所以定义x,y表示坐标,d表示方向,模拟一遍指令,对最后的x,y,d做判断就行了。

 

1000P ChildlessNumbers

 

定义D(x)是x的各个位的数字之和,让Y= X/D(X),如果Y是整数,那么就称Y是X的parent, 如果一个数Y没有一个这样的X,让Y是X的parent,那么就称Y是childless的。给出A, B(1<=A<=B<=10^9 且 B-A<=10000),问[A,B]中有多少个数是childless的。

 

这道题比赛时候没有做出来,当时觉得像这种已知结果求初始值的类型,用类似素数的筛选法比较靠谱,用后面的大范围的那段数将A-B之间的数筛掉,YY了很久无果。看了大牛们代码,恍然大悟。

 

其实思路是很简单的,只要枚举A-B间每一个数,做一个判断就行了,关键是判断的时候要想通一个地方。假设是判断a是否为childless,那么从1开始枚举乘a的数i,将积的各个数字和与i比较,相同就说明a是a*i的parent,也就不是childless。问题是i从1枚举到多少呢,其实发现了a的范围不过10^9,那么(a*i)与i的关系是(a*i)的各个位的数加起来与i相等,假设i==100, (a*i)是10^11范围内, 就算这个数的11位全是9,那么各位和也只有99,小于i的100, 所以将i的上限设为100就行了。复杂度O(10^6*100)。

 

 

 

DIV1

 

250P SequenceOfCommands

 

同DIV2 500P

 

 

500P RightTriangle

 

一个圆的边上有N(1<=N<=1e6)个点均匀排布,在其中选M(1<=M<=1e5)个点,选择的策略是,选择大于等于Pos = (a*m*m+b*m+c)%N,且之前没有选过的点作为第m个点,问这M个点中有多少个直角三角形。

 

在圆上找三点形成直角三角形,必然有两点连线通过圆心,另外的M-2个点作为第三点,这样就形成了M-2个直角三角形了。所以只要算出连线通过圆心的点的个数cnt,乘上M-2,就是答案了。另外可以注意到如果N为奇数时,不可能会有两点连线通过圆心。

 

这道题处理的难点在,如何快速找到大于等于pos的之前没有选过的点。如果直接模拟,开个N大的数组一个个往后查,很可能会超时。于是想到了类似并查集路径压缩的数组标记的方法。next[i]表示大于等于i的第一个可能空位置,初始时全是空,next[i]初始化为i。Find(i)用来查找大于等于i的最近空位置,找到一个空位置pos后,将next[pos] = (pos+1)%N,递归回来的时候,将路上的标记直接设置为当前找到的最近空位置pos,压缩路径。

int Find(int index)   //查找大于等于index的最近空位置
{
    if(next[index]==index) //当前就是空位置
    {
           next[index] = (index+1)%N;   //当前被选中后,就假设下一个位置是空位置(如果下一个不是空也没关系,因为会递归传递)
           return index;
    }
    else
    {
          int pos = Find(next[index]);  //找到自己下一个位置的最近空位置(因为这里会有传递,所以上面是没关系的)
          next[index] = pos;   //将自己的最近空位置设置为pos,(其实也可以设置为(pos+1)%N,原因看上一个括号)
          return pos;
     }
}

 

 

1000P RooksParty

 

在row*col(30*30)的棋盘,放置共K(1<=K<=10)种不同颜色的棋子,每种颜色的棋子有cnt[k]个(0<=k < K),将这些棋子全部放置在棋盘上且不能冲突,冲突是指不同颜色的棋子在同行或同列。问能有多少种放置的方法。

 

留空

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值