[Avito Cool Challenge 2018] 小结 A,C,E+听来的B
前言
上次的Educational Codeforces Round 56 (Rated for Div. 2) 由于 \n
引发了一系列惨案,再加上题目也不是很难,在此就不赘述了手动滑稽,分数还是记录一下:1453 → 1385
。
这场Avito Cool Challenge 2018基本算是数学场吧,orz,虽然是合场,但是辣鸡本人还是只出了三个题。上来 2min
A题莽了一发的时候还是有点忐忑的,但是大神们都很快,嘤嘤嘤,还好抓住了关键点。B题以为是握手定理,虽然解释的通,但是完全不会写,后来下场了问了队友才知道想复杂了,orz。C题拿到手一看就是组合数学嘛,(虽然队友说可以dp),但是逆元没写过啊啊啊啊阿,查资料加试错,60min
才写出来,而且WA了六发,本体得分最低。后来开D,也是很玄学了,明明下午CSP才了一个类似的最短路,居然题意没看懂,也是醉不行。不懂没关系,我们可以看后面的嘛, 90min
的时候码了一个优化的很弱的E,居然一发过了也是很忐忑。后面的时间,就是专心B了,无果。成绩记录 :1385→ 1492
A. Definite Game
题意
就是有一个数,不断减去和他互质的数,最后能得到的最小数是多少。样例给的很有迷惑性,实际上除了2,n和n-1都互质。
代码
int main()
{
int n;
scanf("%d",&n);
if(n==2)
printf("2\n");
else
printf("1\n");
}
C. Colorful Bricks
题意
有n块的砖头摆在一起,有m种颜料,染色后,有k块和左边的颜色不一样,有多少种不同的染色方法。
做法
非常经典的组合题,咳咳,的一个叠加。公式如下:
我们来分解一下,对于每一处的k,其实就是一处分界面,我们需要在n-1个缝隙之间,找到k个,这是非常经典的隔板法,然后,由k个隔板隔开的k+1段,需要染上相邻不同的颜色,第一块,有m种,剩下的都只有m-1种。
此外,还有一个点就是逆元的运用了,将除法的取模转化为乘法。
代码
long long inv[2005];
void get_inverse(long long n,long long p)
{
long long i;
inv[1]=1;
for(i=2;i<=n;++i)
inv[i]=(p-p/i)*inv[p%i]%p;
}
int main()
{
long long n,m,k;
scanf("%lld%lld%lld",&n,&m,&k);
long long ans = 1;
get_inverse(n,mod);
if(k==0)
{
printf("%d",m);
return 0;
}
for(int i=1;i<=min(k,n-k-1);i++) //用min来控制了一下,可以去掉
{
ans= (ans*(n-i))%mod;
ans= (ans*inv[i])%mod;
}
ans = (ans*m)%mod;
for(int i=1;i<k+1;i++)
{
ans = (ans*(m-1))%mod;
}
printf("%lld\n",ans);
}
E. Missing Numbers
题意
给定一个数组的偶数位,求我们能否给出一个完整的数列,使得此数列的每一个前缀和都是平方数。
做法
数学归纳法推出,假设前2k为已经成立,将第2k+2加入到前缀和中,求出一个前2k+2项和的平方根的下限,判断前2k+1的前缀和是否为平方数,若不满足,则调整2k+2的前缀和的大小。给定退出循环的条件,因为两个平方和的差一定不能大于给定数的一半加一(此关系可以根据平方差公式和不等式关系推出)
做法
long long num[100010];
long long ans[100010];
int main()
{
int n;
scanf("%d",&n);
long long sum = 0;
long long tmp = 0;
long long lasttmp = 0;
for(int i=0;i<n/2;i++)
{
scanf("%d",&num[i]);
sum += num[i];
lasttmp = tmp;
tmp = sqrt(sum)+1;
while(true)
{
sum = tmp*tmp;
long long diff = sum - num[i];
long long sq = sqrt(diff);
if(sq*sq==diff)
{
break;
}
tmp++;
if(tmp>num[i]/2+1)
{
printf("No\n");
return 0;
}
}
ans[i] = tmp*tmp -num[i]- lasttmp*lasttmp;
if(ans[i]>1e13)
{
printf("No\n");
return 0;
}
}
printf("Yes\n");
for(int i=0;i<n/2;i++)
{
printf("%lld %lld ",ans[i],num[i]);
}
printf("\n");
}
后话
最近有点忙哈,B题就先咕咕咕了,基本思路是集合的数量查找,嘿嘿嘿,希望我biubiubiu学长不会看见,略略略